fix(ui):优化下拉框被其他组件遮挡的问题
This commit is contained in:
1 parent
0e3cecf144
commit
ec0f815a53
9 files changed
+138
-135
No files matched your search
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, h } from 'vue'
|
||||
import { NForm, NFormItem, NInput, NSelect, NDatePicker, NInputNumber, NButton, NDrawer, NDrawerContent } from 'naive-ui'
|
||||
import { NForm, NFormItem, NInput, NSelect, NDatePicker, NInputNumber, NButton, NDrawer, NDrawerContent, NDropdown } from 'naive-ui'
|
||||
import Icon from './Icon.vue'
|
||||
import MobileRangeFilter from './MobileRangeFilter.vue'
|
||||
|
||||
@@ -49,9 +49,17 @@ const emit = defineEmits<{
|
||||
// 表单数据(由父组件通过 v-model 绑定)
|
||||
const modelValue = defineModel<Record<string, any>>({ required: true })
|
||||
|
||||
const showExportDropdown = ref(false)
|
||||
const showFilterDrawer = ref(false)
|
||||
|
||||
// 导出格式下拉选项(NDropdown 默认 teleport 到 body,避免被 .card 的 backdrop-filter
|
||||
// stacking context 困住而被下方表格面板遮挡)
|
||||
const exportDropdownOptions = computed(() =>
|
||||
props.exportFormats.map(format => ({
|
||||
label: format === 'csv' ? '导出 CSV' : '导出 Excel',
|
||||
key: format,
|
||||
}))
|
||||
)
|
||||
|
||||
// 检测是否为移动端
|
||||
const isMobile = ref(false)
|
||||
const checkMobile = () => {
|
||||
@@ -104,9 +112,8 @@ function handleReset() {
|
||||
emit('reset')
|
||||
}
|
||||
|
||||
function handleExport(format: 'csv' | 'xlsx') {
|
||||
showExportDropdown.value = false
|
||||
emit('export', format)
|
||||
function handleExport(format: string | number) {
|
||||
emit('export', format as 'csv' | 'xlsx')
|
||||
}
|
||||
|
||||
// 日期时间范围默认快捷选项
|
||||
@@ -243,39 +250,19 @@ const renderField = (field: FilterField) => {
|
||||
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- 导出按钮 -->
|
||||
<div v-if="showExport" class="relative">
|
||||
<n-button
|
||||
:loading="exporting"
|
||||
:disabled="exporting"
|
||||
@click="showExportDropdown = !showExportDropdown"
|
||||
>
|
||||
<n-dropdown
|
||||
v-if="showExport"
|
||||
trigger="click"
|
||||
:options="exportDropdownOptions"
|
||||
@select="handleExport"
|
||||
>
|
||||
<n-button :loading="exporting" :disabled="exporting">
|
||||
<template #icon>
|
||||
<Icon name="download" size="sm" />
|
||||
</template>
|
||||
导出
|
||||
</n-button>
|
||||
<div
|
||||
v-if="showExportDropdown"
|
||||
class="absolute right-0 z-50 mt-2 w-36 overflow-hidden rounded-lg border border-gray-200 bg-white py-1 shadow-lg"
|
||||
>
|
||||
<button
|
||||
v-if="exportFormats.includes('csv')"
|
||||
type="button"
|
||||
class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50"
|
||||
@click="handleExport('csv')"
|
||||
>
|
||||
导出 CSV
|
||||
</button>
|
||||
<button
|
||||
v-if="exportFormats.includes('xlsx')"
|
||||
type="button"
|
||||
class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50"
|
||||
@click="handleExport('xlsx')"
|
||||
>
|
||||
导出 Excel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
|
||||
<!-- 自定义额外按钮插槽 -->
|
||||
<slot name="extra-actions" />
|
||||
@@ -356,12 +343,12 @@ const renderField = (field: FilterField) => {
|
||||
<!-- 导出按钮 -->
|
||||
<template v-if="showExport">
|
||||
<span class="mx-1 h-6 w-px bg-gray-200" aria-hidden="true"></span>
|
||||
<div class="relative">
|
||||
<n-button
|
||||
:loading="exporting"
|
||||
:disabled="exporting"
|
||||
@click="showExportDropdown = !showExportDropdown"
|
||||
>
|
||||
<n-dropdown
|
||||
trigger="click"
|
||||
:options="exportDropdownOptions"
|
||||
@select="handleExport"
|
||||
>
|
||||
<n-button :loading="exporting" :disabled="exporting">
|
||||
<template #icon>
|
||||
<Icon name="download" size="sm" />
|
||||
</template>
|
||||
@@ -370,28 +357,7 @@ const renderField = (field: FilterField) => {
|
||||
<Icon name="chevronDown" size="xs" />
|
||||
</template>
|
||||
</n-button>
|
||||
<div
|
||||
v-if="showExportDropdown"
|
||||
class="absolute right-0 z-50 mt-2 w-36 overflow-hidden rounded-lg border border-gray-200 bg-white py-1 shadow-lg"
|
||||
>
|
||||
<button
|
||||
v-if="exportFormats.includes('csv')"
|
||||
type="button"
|
||||
class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50"
|
||||
@click="handleExport('csv')"
|
||||
>
|
||||
导出 CSV
|
||||
</button>
|
||||
<button
|
||||
v-if="exportFormats.includes('xlsx')"
|
||||
type="button"
|
||||
class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50"
|
||||
@click="handleExport('xlsx')"
|
||||
>
|
||||
导出 Excel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
</template>
|
||||
|
||||
<!-- 自定义额外按钮插槽 -->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, h } from 'vue'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { NButton } from 'naive-ui'
|
||||
import { NButton, NDropdown } from 'naive-ui'
|
||||
import Icon from '@/components/common/Icon.vue'
|
||||
import ResponsiveDataTable from '@/components/common/ResponsiveDataTable.vue'
|
||||
import { renderBadge, formatMoney, tableScrollX } from '@/utils/renderUtils'
|
||||
@@ -15,7 +15,16 @@ const pageSize = ref(20)
|
||||
const total = ref(0)
|
||||
const statusFilter = ref('')
|
||||
|
||||
const showExportDropdown = ref(false)
|
||||
// 导出格式下拉选项(NDropdown 默认 teleport 到 body,避免被 .card 的 backdrop-filter
|
||||
// stacking context 困住而被下方表格面板遮挡)
|
||||
const exportDropdownOptions = [
|
||||
{ label: '导出 CSV', key: 'csv' },
|
||||
{ label: '导出 Excel', key: 'xlsx' },
|
||||
]
|
||||
|
||||
function handleExport(format: string | number) {
|
||||
exportFile(format as 'csv' | 'xlsx')
|
||||
}
|
||||
const { exporting, exportFile } = useExport({
|
||||
url: '/tenant/orders/export',
|
||||
getFilters: () => ({
|
||||
@@ -162,17 +171,14 @@ onMounted(() => {
|
||||
<p class="page-description">查看所有订阅和充值订单</p>
|
||||
</div>
|
||||
<!-- Export dropdown -->
|
||||
<div class="relative inline-block">
|
||||
<button class="btn btn-secondary btn-sm" :disabled="exporting" @click="showExportDropdown = !showExportDropdown">
|
||||
<svg v-if="!exporting" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"/></svg>
|
||||
<svg v-else class="h-4 w-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
|
||||
<n-dropdown trigger="click" :options="exportDropdownOptions" @select="handleExport">
|
||||
<button type="button" class="btn btn-secondary btn-sm" :disabled="exporting">
|
||||
<Icon v-if="exporting" name="refresh" size="sm" class="animate-spin" />
|
||||
<Icon v-else name="download" size="sm" />
|
||||
导出
|
||||
<Icon name="chevronDown" size="xs" />
|
||||
</button>
|
||||
<div v-if="showExportDropdown" class="absolute right-0 mt-2 w-36 bg-white rounded-xl border shadow-lg py-1 z-50">
|
||||
<div class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer" @click="exportFile('csv'); showExportDropdown = false">导出 CSV</div>
|
||||
<div class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer" @click="exportFile('xlsx'); showExportDropdown = false">导出 Excel</div>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, h } from 'vue'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { NInput, NInputNumber, NSelect } from 'naive-ui'
|
||||
import { NInput, NInputNumber, NSelect, NDropdown } from 'naive-ui'
|
||||
import Icon from '@/components/common/Icon.vue'
|
||||
import DateRangePicker from '@/components/common/DateRangePicker.vue'
|
||||
import ResponsiveDataTable from '@/components/common/ResponsiveDataTable.vue'
|
||||
@@ -32,8 +32,16 @@ const filters = ref({
|
||||
model: '',
|
||||
})
|
||||
|
||||
// 导出下拉菜单
|
||||
const showExportDropdown = ref(false)
|
||||
// 导出格式下拉选项(NDropdown 默认 teleport 到 body,避免被 .card 的 backdrop-filter
|
||||
// stacking context 困住而被下方表格面板遮挡)
|
||||
const exportDropdownOptions = [
|
||||
{ label: '导出 CSV', key: 'csv' },
|
||||
{ label: '导出 Excel', key: 'xlsx' },
|
||||
]
|
||||
|
||||
function handleExport(format: string | number) {
|
||||
exportFile(format as 'csv' | 'xlsx')
|
||||
}
|
||||
|
||||
const { exporting, exportFile } = useExport({
|
||||
url: '/tenant/wallet/transactions/export',
|
||||
@@ -231,18 +239,14 @@ onMounted(fetchTransactions)
|
||||
刷新
|
||||
</button>
|
||||
<span class="mx-1 h-6 w-px bg-gray-200" aria-hidden="true"></span>
|
||||
<div class="relative">
|
||||
<button type="button" class="btn btn-secondary btn-sm" :disabled="exporting || loading" @click="showExportDropdown = !showExportDropdown">
|
||||
<n-dropdown trigger="click" :options="exportDropdownOptions" @select="handleExport">
|
||||
<button type="button" class="btn btn-secondary btn-sm" :disabled="exporting || loading">
|
||||
<Icon v-if="exporting" name="refresh" size="sm" class="animate-spin" />
|
||||
<Icon v-else name="download" size="sm" />
|
||||
导出
|
||||
<Icon name="chevronDown" size="xs" />
|
||||
</button>
|
||||
<div v-if="showExportDropdown" class="absolute right-0 z-50 mt-2 w-36 overflow-hidden rounded-lg border border-gray-200 bg-white py-1 shadow-lg">
|
||||
<button type="button" class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50" @click="exportFile('csv'); showExportDropdown = false">导出 CSV</button>
|
||||
<button type="button" class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50" @click="exportFile('xlsx'); showExportDropdown = false">导出 Excel</button>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { NDropdown } from 'naive-ui'
|
||||
import Icon from '@/components/common/Icon.vue'
|
||||
import BasePagination from '@/components/common/BasePagination.vue'
|
||||
import request from '@/utils/request'
|
||||
@@ -23,7 +24,16 @@ const pageSize = ref(20)
|
||||
const total = ref(0)
|
||||
const activeTab = ref<'all' | 'unread'>('all')
|
||||
|
||||
const showExportDropdown = ref(false)
|
||||
// 导出格式下拉选项(NDropdown 默认 teleport 到 body,避免被 .card 的 backdrop-filter
|
||||
// stacking context 困住而被下方表格面板遮挡)
|
||||
const exportDropdownOptions = [
|
||||
{ label: '导出 CSV', key: 'csv' },
|
||||
{ label: '导出 Excel', key: 'xlsx' },
|
||||
]
|
||||
|
||||
function handleExport(format: string | number) {
|
||||
exportFile(format as 'csv' | 'xlsx')
|
||||
}
|
||||
const { exporting, exportFile } = useExport({
|
||||
url: '/tenant/notifications/export',
|
||||
})
|
||||
@@ -125,17 +135,14 @@ onMounted(() => {
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- Export dropdown -->
|
||||
<div class="relative inline-block">
|
||||
<button class="btn btn-secondary" :disabled="exporting" @click="showExportDropdown = !showExportDropdown">
|
||||
<svg v-if="!exporting" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"/></svg>
|
||||
<svg v-else class="h-4 w-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
|
||||
<n-dropdown trigger="click" :options="exportDropdownOptions" @select="handleExport">
|
||||
<button type="button" class="btn btn-secondary" :disabled="exporting">
|
||||
<Icon v-if="exporting" name="refresh" size="sm" class="animate-spin" />
|
||||
<Icon v-else name="download" size="sm" />
|
||||
导出
|
||||
<Icon name="chevronDown" size="xs" />
|
||||
</button>
|
||||
<div v-if="showExportDropdown" class="absolute right-0 mt-2 w-36 bg-white rounded-xl border shadow-lg py-1 z-50">
|
||||
<div class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer" @click="exportFile('csv'); showExportDropdown = false">导出 CSV</div>
|
||||
<div class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer" @click="exportFile('xlsx'); showExportDropdown = false">导出 Excel</div>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
<button class="btn btn-secondary" @click="markAllRead" :disabled="unreadCount === 0">
|
||||
<Icon name="check" size="sm" />
|
||||
全部已读
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, h } from 'vue'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { NButton, NTag } from 'naive-ui'
|
||||
import { NButton, NTag, NDropdown } from 'naive-ui'
|
||||
import BaseModal from '@/components/common/BaseModal.vue'
|
||||
import ResponsiveDataTable from '@/components/common/ResponsiveDataTable.vue'
|
||||
import ApiKeyEditModal from '@/components/common/ApiKeyEditModal.vue'
|
||||
@@ -41,7 +41,16 @@ const page = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const total = ref(0)
|
||||
|
||||
const showExportDropdown = ref(false)
|
||||
// 导出格式下拉选项(NDropdown 默认 teleport 到 body,避免被 .card 的 backdrop-filter
|
||||
// stacking context 困住而被下方表格面板遮挡)
|
||||
const exportDropdownOptions = [
|
||||
{ label: '导出 CSV', key: 'csv' },
|
||||
{ label: '导出 Excel', key: 'xlsx' },
|
||||
]
|
||||
|
||||
function handleExport(format: string | number) {
|
||||
exportFile(format as 'csv' | 'xlsx')
|
||||
}
|
||||
const { exporting, exportFile } = useExport({
|
||||
url: '/tenant/api-keys/export',
|
||||
getFilters: () => ({
|
||||
@@ -298,17 +307,14 @@ onMounted(() => {
|
||||
</div>
|
||||
<div class="flex flex-wrap items-center gap-2 lg:flex-none">
|
||||
<!-- Export dropdown -->
|
||||
<div class="relative inline-block">
|
||||
<button class="btn btn-secondary" :disabled="exporting" @click="showExportDropdown = !showExportDropdown">
|
||||
<svg v-if="!exporting" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"/></svg>
|
||||
<svg v-else class="h-4 w-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
|
||||
<n-dropdown trigger="click" :options="exportDropdownOptions" @select="handleExport">
|
||||
<button type="button" class="btn btn-secondary" :disabled="exporting">
|
||||
<Icon v-if="exporting" name="refresh" size="sm" class="animate-spin" />
|
||||
<Icon v-else name="download" size="sm" />
|
||||
导出
|
||||
<Icon name="chevronDown" size="xs" />
|
||||
</button>
|
||||
<div v-if="showExportDropdown" class="absolute right-0 mt-2 w-36 bg-white rounded-xl border shadow-lg py-1 z-50">
|
||||
<div class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer" @click="exportFile('csv'); showExportDropdown = false">导出 CSV</div>
|
||||
<div class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer" @click="exportFile('xlsx'); showExportDropdown = false">导出 Excel</div>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
<button class="btn btn-primary" @click="showCreateModal = true">
|
||||
<Icon name="plus" size="sm" />
|
||||
创建密钥
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, h } from 'vue'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { NButton, NTag, NInput } from 'naive-ui'
|
||||
import { NButton, NTag, NInput, NDropdown } from 'naive-ui'
|
||||
import { useRoute } from 'vue-router'
|
||||
import Icon from '@/components/common/Icon.vue'
|
||||
import BaseModal from '@/components/common/BaseModal.vue'
|
||||
@@ -57,7 +57,16 @@ const filterPlatform = ref('')
|
||||
const filterTaskId = ref('')
|
||||
const filterStartDate = ref(todayStart())
|
||||
const filterEndDate = ref(todayEnd())
|
||||
const showExportDropdown = ref(false)
|
||||
// 导出格式下拉选项(NDropdown 默认 teleport 到 body,避免被 .card 的 backdrop-filter
|
||||
// stacking context 困住而被下方表格面板遮挡)
|
||||
const exportDropdownOptions = [
|
||||
{ label: '导出 CSV', key: 'csv' },
|
||||
{ label: '导出 Excel', key: 'xlsx' },
|
||||
]
|
||||
|
||||
function handleExport(format: string | number) {
|
||||
exportFile(format as 'csv' | 'xlsx')
|
||||
}
|
||||
|
||||
const showDetail = ref(false)
|
||||
const detailLoading = ref(false)
|
||||
@@ -261,7 +270,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<div class="viewport-table-page space-y-6">
|
||||
<!-- Filters -->
|
||||
<div class="relative z-20 overflow-visible card">
|
||||
<div class="card">
|
||||
<div class="card-body !p-4">
|
||||
<form class="flex flex-wrap items-center gap-x-3 gap-y-3" @submit.prevent="applyFilters">
|
||||
<DateTimeRangePicker
|
||||
@@ -288,18 +297,14 @@ onMounted(() => {
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary btn-sm" @click="resetFilters">重置</button>
|
||||
<span class="mx-1 h-6 w-px bg-gray-200" aria-hidden="true"></span>
|
||||
<div class="relative">
|
||||
<button type="button" class="btn btn-secondary btn-sm" :disabled="exporting || loading" @click="showExportDropdown = !showExportDropdown">
|
||||
<n-dropdown trigger="click" :options="exportDropdownOptions" @select="handleExport">
|
||||
<button type="button" class="btn btn-secondary btn-sm" :disabled="exporting || loading">
|
||||
<Icon v-if="exporting" name="refresh" size="sm" class="animate-spin" />
|
||||
<Icon v-else name="download" size="sm" />
|
||||
导出
|
||||
<Icon name="chevronDown" size="xs" />
|
||||
</button>
|
||||
<div v-if="showExportDropdown" class="absolute right-0 z-50 mt-2 w-36 overflow-hidden rounded-lg border border-gray-200 bg-white py-1 shadow-lg">
|
||||
<button type="button" class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50" @click="exportFile('csv'); showExportDropdown = false">导出 CSV</button>
|
||||
<button type="button" class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50" @click="exportFile('xlsx'); showExportDropdown = false">导出 Excel</button>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, h } from 'vue'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { NButton, NInput, NSelect } from 'naive-ui'
|
||||
import { NButton, NInput, NSelect, NDropdown } from 'naive-ui'
|
||||
import { useRouter } from 'vue-router'
|
||||
import Icon from '@/components/common/Icon.vue'
|
||||
import BaseModal from '@/components/common/BaseModal.vue'
|
||||
@@ -45,8 +45,16 @@ const filters = ref({
|
||||
requestType: '',
|
||||
})
|
||||
|
||||
// 导出下拉菜单
|
||||
const showExportDropdown = ref(false)
|
||||
// 导出格式下拉选项(NDropdown 默认 teleport 到 body,避免被 .card 的 backdrop-filter
|
||||
// stacking context 困住而被下方表格面板遮挡)
|
||||
const exportDropdownOptions = [
|
||||
{ label: '导出 CSV', key: 'csv' },
|
||||
{ label: '导出 Excel', key: 'xlsx' },
|
||||
]
|
||||
|
||||
function handleExport(format: string | number) {
|
||||
exportFile(format as 'csv' | 'xlsx')
|
||||
}
|
||||
|
||||
const { exporting, exportFile } = useExport({
|
||||
url: '/tenant/usage-logs/export',
|
||||
@@ -500,18 +508,14 @@ onMounted(() => {
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary btn-sm" @click="resetFilters">重置</button>
|
||||
<span class="mx-1 h-6 w-px bg-gray-200" aria-hidden="true"></span>
|
||||
<div class="relative">
|
||||
<button type="button" class="btn btn-secondary btn-sm" :disabled="exporting || loading" @click="showExportDropdown = !showExportDropdown">
|
||||
<n-dropdown trigger="click" :options="exportDropdownOptions" @select="handleExport">
|
||||
<button type="button" class="btn btn-secondary btn-sm" :disabled="exporting || loading">
|
||||
<Icon v-if="exporting" name="refresh" size="sm" class="animate-spin" />
|
||||
<Icon v-else name="download" size="sm" />
|
||||
导出
|
||||
<Icon name="chevronDown" size="xs" />
|
||||
</button>
|
||||
<div v-if="showExportDropdown" class="absolute right-0 z-50 mt-2 w-36 overflow-hidden rounded-lg border border-gray-200 bg-white py-1 shadow-lg">
|
||||
<button type="button" class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50" @click="exportFile('csv'); showExportDropdown = false">导出 CSV</button>
|
||||
<button type="button" class="block w-full px-4 py-2 text-left text-sm text-gray-700 hover:bg-gray-50" @click="exportFile('xlsx'); showExportDropdown = false">导出 Excel</button>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, computed, h } from 'vue'
|
||||
import type { DataTableColumns } from 'naive-ui'
|
||||
import { NInput } from 'naive-ui'
|
||||
import { NInput, NDropdown } from 'naive-ui'
|
||||
import BaseModal from '@/components/common/BaseModal.vue'
|
||||
import ResponsiveDataTable from '@/components/common/ResponsiveDataTable.vue'
|
||||
import Icon from '@/components/common/Icon.vue'
|
||||
@@ -37,7 +37,16 @@ const page = ref(1)
|
||||
const pageSize = ref(20)
|
||||
const total = ref(0)
|
||||
|
||||
const showExportDropdown = ref(false)
|
||||
// 导出格式下拉选项(NDropdown 默认 teleport 到 body,避免被 .card 的 backdrop-filter
|
||||
// stacking context 困住而被下方表格面板遮挡)
|
||||
const exportDropdownOptions = [
|
||||
{ label: '导出 CSV', key: 'csv' },
|
||||
{ label: '导出 Excel', key: 'xlsx' },
|
||||
]
|
||||
|
||||
function handleExport(format: string | number) {
|
||||
exportFile(format as 'csv' | 'xlsx')
|
||||
}
|
||||
const { exporting, exportFile } = useExport({
|
||||
url: '/tenant/tickets/export',
|
||||
})
|
||||
@@ -248,17 +257,14 @@ onMounted(() => {
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<!-- Export dropdown -->
|
||||
<div class="relative inline-block">
|
||||
<button class="btn btn-secondary" :disabled="exporting" @click="showExportDropdown = !showExportDropdown">
|
||||
<svg v-if="!exporting" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3"/></svg>
|
||||
<svg v-else class="h-4 w-4 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"/></svg>
|
||||
<n-dropdown trigger="click" :options="exportDropdownOptions" @select="handleExport">
|
||||
<button type="button" class="btn btn-secondary" :disabled="exporting">
|
||||
<Icon v-if="exporting" name="refresh" size="sm" class="animate-spin" />
|
||||
<Icon v-else name="download" size="sm" />
|
||||
导出
|
||||
<Icon name="chevronDown" size="xs" />
|
||||
</button>
|
||||
<div v-if="showExportDropdown" class="absolute right-0 mt-2 w-36 bg-white rounded-xl border shadow-lg py-1 z-50">
|
||||
<div class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer" @click="exportFile('csv'); showExportDropdown = false">导出 CSV</div>
|
||||
<div class="px-4 py-2 text-sm text-gray-700 hover:bg-gray-50 cursor-pointer" @click="exportFile('xlsx'); showExportDropdown = false">导出 Excel</div>
|
||||
</div>
|
||||
</div>
|
||||
</n-dropdown>
|
||||
<button class="btn btn-primary" @click="showCreateModal = true">
|
||||
<Icon name="plus" size="sm" />
|
||||
新建工单
|
||||
|
||||
@@ -35,7 +35,6 @@ const filterFields: FilterField[] = [
|
||||
},
|
||||
]
|
||||
|
||||
const showExportDropdown = ref(false)
|
||||
const showMoreMenu = ref(false)
|
||||
const { exporting, exportFile } = useExport({
|
||||
url: '/tenant/members/export',
|
||||
|
||||
Reference in new issue
Block a user