页签导航栏

This commit is contained in:
2026-05-21 14:22:51 +08:00
parent f0aa2625e9
commit 3f1ad80a8f
6 changed files with 154 additions and 99 deletions

View File

@ -22,9 +22,9 @@
>
<router-view v-slot="{ Component }">
<KeepAlive v-if="route.meta.keepAlive">
<component :is="Component" :key="route.path" />
<component :is="Component" :key="refreshKey" />
</KeepAlive>
<component v-else :is="Component" :key="route.path" />
<component v-else :is="Component" :key="refreshKey" />
</router-view>
</transition>
</main>
@ -40,8 +40,19 @@ defineOptions({
import Header from './Header.vue'
import Sidebar from './Sidebar.vue'
import Tabs from './Tabs.vue'
import { useTabsStore } from '@/stores/modules/tabs'
const route = useRoute()
const tabsStore = useTabsStore()
// key
const refreshKey = computed(() => {
// refreshKey
if (tabsStore.refreshKey.startsWith(route.path)) {
return tabsStore.refreshKey
}
return route.path
})
//
const sidebarCollapsed = ref(false)

View File

@ -82,7 +82,11 @@
:style="contextMenuStyle"
@click.stop
>
<div class="context-menu-item" @click="handleContextMenuCommand('refresh')">
<div
class="context-menu-item"
:class="{ 'is-disabled': !canRefresh }"
@click="canRefresh && handleContextMenuCommand('refresh')"
>
<el-icon><Refresh /></el-icon>
<span>刷新当前页</span>
</div>
@ -140,6 +144,12 @@ const canCloseCurrent = computed(() => {
return !isFixedTab(path)
})
// tab
const canRefresh = computed(() => {
const path = contextMenuPath.value || ''
return path === route.path
})
//
const canCloseOther = computed(() => {
const path = contextMenuPath.value || tabsStore.activeTab || ''
@ -393,11 +403,32 @@ const handleDragEnd = () => {
const handleContextMenuCommand = (command: string) => {
// 使
const currentPath = contextMenuPath.value || tabsStore.activeTab
//
const rightClickedPath = contextMenuPath.value
closeContextMenu()
switch (command) {
case 'refresh':
router.go(0)
// tab tab
const refreshPath = rightClickedPath || tabsStore.activeTab
if (refreshPath) {
const targetTab = tabsStore.tabs.find(item => item.path === refreshPath)
// activeTab
if (refreshPath !== route.path) {
tabsStore.setActiveTab(refreshPath)
router.push({ path: refreshPath, query: targetTab?.query }).then(() => {
//
nextTick(() => {
tabsStore.refreshTab(refreshPath)
})
})
} else {
//
tabsStore.refreshTab(refreshPath)
}
}
break
case 'close':
if (currentPath) {

View File

@ -241,6 +241,14 @@ export const useTabsStore = defineStore('tabs', () => {
saveTabs()
}
// 刷新指定 tab 的 key用于触发组件刷新
const refreshKey = ref<string>('')
// 刷新指定路径的 tab
const refreshTab = (path: string) => {
refreshKey.value = path + '-' + Date.now()
}
// 保存到本地存储
const saveTabs = () => {
setStorage('tabs', tabs.value)
@ -283,6 +291,8 @@ export const useTabsStore = defineStore('tabs', () => {
closeRightTabs,
setActiveTab,
clearTabs,
setTabs
setTabs,
refreshKey,
refreshTab
}
})

View File

@ -1,3 +1,6 @@
import dayjs from 'dayjs'
/**
*
* @param format 'YYYY-MM-DD HH:mm:ss'
@ -37,22 +40,22 @@ export const getRecentSevenDays = (format = 'YYYY-MM-DD HH:mm:ss'):{ start: stri
* @returns {string} UTC+8 YYYY-MM-DD HH:mm:ss
*/
export function utcToUtc8(utcStr: string): string {
// 将字符串解析为 UTC 时间
const utcDate = new Date(utcStr.replace(' ', 'T') + 'Z')
// // 将字符串解析为 UTC 时间
// const utcDate = new Date(utcStr.replace(' ', 'T') + 'Z')
// 转换为 UTC+8东八区
const utc8Date = new Date(utcDate.getTime() + 8 * 60 * 60 * 1000)
// // 转换为 UTC+8东八区
// const utc8Date = new Date(utcDate.getTime() + 8 * 60 * 60 * 1000)
// 格式化为 YYYY-MM-DD HH:mm:ss
const pad = (n) => String(n).padStart(2, '0')
// // 格式化为 YYYY-MM-DD HH:mm:ss
// const pad = (n) => String(n).padStart(2, '0')
const year = utc8Date.getUTCFullYear()
const month = pad(utc8Date.getUTCMonth() + 1)
const day = pad(utc8Date.getUTCDate())
const hour = pad(utc8Date.getUTCHours())
const minute = pad(utc8Date.getUTCMinutes())
const second = pad(utc8Date.getUTCSeconds())
// const year = utc8Date.getUTCFullYear()
// const month = pad(utc8Date.getUTCMonth() + 1)
// const day = pad(utc8Date.getUTCDate())
// const hour = pad(utc8Date.getUTCHours())
// const minute = pad(utc8Date.getUTCMinutes())
// const second = pad(utc8Date.getUTCSeconds())
return `${year}-${month}-${day} ${hour}:${minute}:${second}`
return dayjs(utcStr).format('YYYY-MM-DD HH:mm:ss')
}

View File

@ -1,12 +1,8 @@
<template>
<div class="table_form-container">
<!-- 搜索 -->
<FundDetailSearch
:search-form="searchForm"
:search-options="searchOptions"
@search="handleSearch"
@reset="handleReset"
>
<FundDetailSearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch"
@reset="handleReset">
<template #button="{ form }">
<el-button type="primary" @click="handleExport()"> 导出 </el-button>
</template>
@ -14,12 +10,8 @@
<!-- 表格 -->
<FundDetailTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="id" :loading="loading" />
<!-- 分页 -->
<FundDetailPagination
v-model="currentPage"
v-model:pageSizeValue="pageSize"
:total="total"
@pagination-change="handlePaginationChange"
/>
<FundDetailPagination v-model="currentPage" v-model:pageSizeValue="pageSize" :total="total"
@pagination-change="handlePaginationChange" />
</div>
</template>
@ -71,41 +63,44 @@ const total = ref(0)
//
const getFundDetailList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
start_time:
searchForm.value.startTime.length > 0
? `${searchForm.value.startTime} 0:00:00`
: '2026-01-01 0:00:00',
end_time:
searchForm.value.endTime.length > 0
? `${searchForm.value.endTime} 23:59:59`
: '2026-03-15 23:59:59',
user_name: searchForm.value.username,
account_id: searchForm.value.subAccountId,
}
//
const data: any = await getFundDetailListApi(params)
stopLoading()
console.log(data)
tableTree.value = data.data.map((item: any) => ({
try {
const params = {
page: currentPage.value,
page_size: pageSize.value,
start_time:
searchForm.value.startTime.length > 0
? `${searchForm.value.startTime} 0:00:00`
: '2026-01-01 0:00:00',
end_time:
searchForm.value.endTime.length > 0
? `${searchForm.value.endTime} 23:59:59`
: '2026-03-15 23:59:59',
user_name: searchForm.value.username,
account_id: searchForm.value.subAccountId,
}
//
const data: any = await getFundDetailListApi(params)
console.log(data)
tableTree.value = data.data.map((item: any) => ({
...item,
//
username: item.user.username,
//
orderNo: item.trade_id,
//
type: item.enum_dic.value,
//
createTime: utcToUtc8(item.created_at),
//
walletType: item.wallet_type === '1' ? '主钱包' : '子钱包',
}))
//
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
//
username: item.user.username,
//
orderNo: item.trade_id,
//
type: item.enum_dic.value,
//
createTime: utcToUtc8(item.created_at),
//
walletType: item.wallet_type === '1' ? '主钱包' : '子钱包',
}))
//
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
} finally {
stopLoading()
}
}
/**

View File

@ -2,7 +2,7 @@
<div class="table_form-container">
<!-- 搜索 -->
<CustomerTradeOrderSearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch"
@reset="handleReset" @blur-input="getSubAccountList">
@reset="handleReset" @blur-input="getSubAccountList">
</CustomerTradeOrderSearch>
<div class="bar" v-if="searchForm.orderId === '1'">
<div>持仓量:0</div>
@ -10,7 +10,8 @@
<div>交易盈亏:0.00 USD</div>
</div>
<!-- 表格 -->
<CustomerTradeOrderTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="id" :loading="loading" />
<CustomerTradeOrderTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="id"
:loading="loading" />
<!-- 分页 -->
<CustomerTradeOrderPagination v-model="currentPage" v-model:pageSizeValue="pageSize" :total="total"
@ -22,7 +23,7 @@
<script setup lang="ts">
defineOptions({
name: 'History'
name: 'History'
})
//
import CustomerTradeOrderSearch from '@/components/common/Search.vue'
@ -82,39 +83,43 @@ const total = ref(0)
* @description: 定义公共请求数据方法
*/
const getCustomerTradeOrderList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
user_name: searchForm.value.accountName,
account_id: searchForm.value.subAccountName,
order_no: '',
type: searchForm.value.tradeType,
start_time: dateRange.start,
end_time: dateRange.end,
}
console.log(params)
const data: any = await getCustomTradeOrderListApi(params)
stopLoading()
//
// table
tableTree.value = data.data.map((item: any) => ({
accountName: item.user.username,
orderId: item.order_id,
variety: item.variety.name,
type: item.type === 1 ? '买入' : '卖出',
quantity: item.num,
openPrice: item.build_price,
closePrice: item.close_price,
closeProfitLoss: item.profit_loss,
amount: item.amount,
createdTime: item.created_at,
}))
try {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
user_name: searchForm.value.accountName,
account_id: searchForm.value.subAccountName,
order_no: '',
type: searchForm.value.tradeType,
start_time: dateRange.start,
end_time: dateRange.end,
}
console.log(params)
const data: any = await getCustomTradeOrderListApi(params)
//
// table
tableTree.value = data.data.map((item: any) => ({
accountName: item.user.username,
orderId: item.order_id,
variety: item.variety.name,
type: item.type === 1 ? '买入' : '卖出',
quantity: item.num,
openPrice: item.build_price,
closePrice: item.close_price,
closeProfitLoss: item.profit_loss,
amount: item.amount,
createdTime: item.created_at,
}))
//
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
//
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
} finally {
stopLoading()
}
}
const getSubAccountList = async () => {