bug
This commit is contained in:
parent
34de6d5679
commit
1d355d822e
|
|
@ -5,9 +5,11 @@
|
||||||
:breakpoint="992"
|
:breakpoint="992"
|
||||||
>
|
>
|
||||||
<TopLoading ref="topLoadingRef" />
|
<TopLoading ref="topLoadingRef" />
|
||||||
<KeepAlive>
|
<router-view v-slot="{ Component }">
|
||||||
<router-view></router-view>
|
<KeepAlive>
|
||||||
</KeepAlive>
|
<component :is="Component" />
|
||||||
|
</KeepAlive>
|
||||||
|
</router-view>
|
||||||
</MobileScale>
|
</MobileScale>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,12 @@
|
||||||
|
|
||||||
<!-- 主体内容区 -->
|
<!-- 主体内容区 -->
|
||||||
<main class="main-content">
|
<main class="main-content">
|
||||||
<transition
|
<router-view v-slot="{ Component }">
|
||||||
name="fade-transform"
|
<transition
|
||||||
mode="out-in"
|
name="fade-transform"
|
||||||
style="height: 100%; display: flex; flex-direction: column"
|
mode="out-in"
|
||||||
>
|
style="height: 100%; display: flex; flex-direction: column"
|
||||||
<router-view v-slot="{ Component }">
|
>
|
||||||
<!-- 使用 :key 确保每次路由变化都会创建新的 ErrorBoundary 实例 -->
|
<!-- 使用 :key 确保每次路由变化都会创建新的 ErrorBoundary 实例 -->
|
||||||
<ErrorBoundary :key="route.path + '-' + refreshKey">
|
<ErrorBoundary :key="route.path + '-' + refreshKey">
|
||||||
<KeepAlive v-if="route.meta.keepAlive">
|
<KeepAlive v-if="route.meta.keepAlive">
|
||||||
|
|
@ -28,8 +28,8 @@
|
||||||
</KeepAlive>
|
</KeepAlive>
|
||||||
<component v-else :is="Component" :key="refreshKey" />
|
<component v-else :is="Component" :key="refreshKey" />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</router-view>
|
</transition>
|
||||||
</transition>
|
</router-view>
|
||||||
</main>
|
</main>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -122,6 +122,7 @@ const handleToggleSidebar = (collapsed: boolean) => {
|
||||||
transition: margin-left 0.3s ease;
|
transition: margin-left 0.3s ease;
|
||||||
|
|
||||||
.main-content {
|
.main-content {
|
||||||
|
background-color: #fff;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@
|
||||||
:default-active="activeMenu"
|
:default-active="activeMenu"
|
||||||
:collapse="collapsed"
|
:collapse="collapsed"
|
||||||
router
|
router
|
||||||
|
@select="handleSelect"
|
||||||
>
|
>
|
||||||
<template v-for="menu in menuList" :key="menu.id">
|
<template v-for="menu in menuList" :key="menu.id">
|
||||||
<!-- 无子菜单 -->
|
<!-- 无子菜单 -->
|
||||||
<el-menu-item v-if="!menu.children || menu.children.length === 0" :index="menu.path">
|
<el-menu-item v-if="!menu.children || menu.children.length === 0" :index="menu.path || `__invalid_${menu.id}`">
|
||||||
<el-icon v-if="menu.icon">
|
<el-icon v-if="menu.icon">
|
||||||
<component :is="iconMap[menu.icon]" />
|
<component :is="iconMap[menu.icon]" />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
|
|
@ -18,7 +19,7 @@
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|
||||||
<!-- 有子菜单 -->
|
<!-- 有子菜单 -->
|
||||||
<el-sub-menu v-else :index="menu.path">
|
<el-sub-menu v-else :index="menu.path || `__invalid_${menu.id}`">
|
||||||
<template #title>
|
<template #title>
|
||||||
<el-icon v-if="menu.icon">
|
<el-icon v-if="menu.icon">
|
||||||
<component :is="iconMap[menu.icon]" />
|
<component :is="iconMap[menu.icon]" />
|
||||||
|
|
@ -28,7 +29,7 @@
|
||||||
<el-menu-item
|
<el-menu-item
|
||||||
v-for="subMenu in menu.children"
|
v-for="subMenu in menu.children"
|
||||||
:key="subMenu.id"
|
:key="subMenu.id"
|
||||||
:index="subMenu.path"
|
:index="subMenu.path || `__invalid_${subMenu.id}`"
|
||||||
>
|
>
|
||||||
<template #title>{{ subMenu.label }}</template>
|
<template #title>{{ subMenu.label }}</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
|
|
@ -49,6 +50,7 @@ import {
|
||||||
WarningFilled,
|
WarningFilled,
|
||||||
Tools,
|
Tools,
|
||||||
} from '@element-plus/icons-vue'
|
} from '@element-plus/icons-vue'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
import { useUserStore } from '@/stores/modules/user'
|
import { useUserStore } from '@/stores/modules/user'
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
|
@ -56,6 +58,7 @@ defineProps<{
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
// 计算当前激活的菜单 index
|
// 计算当前激活的菜单 index
|
||||||
|
|
@ -68,6 +71,24 @@ const menuList = computed(() => {
|
||||||
return userStore.sideMenu || []
|
return userStore.sideMenu || []
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 菜单点击处理:
|
||||||
|
// el-menu 在 router 模式下会根据 :index 跳路径,但当路径在动态路由表中不存在时,
|
||||||
|
// 会触发 :pathMatch(.*)* 兑底被重定向到 /dashboard,造成“点了菜单没反应、过一会自动刷新”。
|
||||||
|
// 这里加一道护栏:路径为空、或者未在已注册路由表中存在时,提示用户并取消跳转。
|
||||||
|
const handleSelect = (index: string) => {
|
||||||
|
if (!index || index.startsWith('__invalid_')) {
|
||||||
|
ElMessage.warning('该菜单暂未配置访问路径,请联系管理员')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 检查路由表中是否已存在该路径
|
||||||
|
const hasExact = router.getRoutes().some((r) => r.path === index)
|
||||||
|
if (!hasExact) {
|
||||||
|
ElMessage.warning('该页面路由未加载,请稍后重试')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// 图标映射表
|
// 图标映射表
|
||||||
const iconMap: Record<string, any> = {
|
const iconMap: Record<string, any> = {
|
||||||
HomeFilled,
|
HomeFilled,
|
||||||
|
|
@ -84,11 +105,11 @@ const iconMap: Record<string, any> = {
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.sidebar {
|
.sidebar {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 60px;
|
top: 50px;
|
||||||
left: 0;
|
left: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
background: var(--el-bg-color-page);
|
background: #fff;
|
||||||
border-right: 1px solid var(--el-border-color-light);
|
border-right: 1px solid var(--el-border-color-light);
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,16 @@ export const handleRouter = (list: any[]):any[] => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setRouter = () => {
|
export const setRouter = () => {
|
||||||
|
|
||||||
const menuList = (getStorage('menusInfo') as any[]) || []
|
const menuList = (getStorage('menusInfo') as any[]) || []
|
||||||
const token = getStorage('token')
|
const token = getStorage('token')
|
||||||
|
|
||||||
// 检查是否已存在 dashboard 路由
|
if (!token) return
|
||||||
const hasDashboardRoute = router.getRoutes().some(
|
|
||||||
(route) => route.path === '/dashboard',
|
// 用 pathname 集合做幂等去重,避免 addRoute 重复添加同名路由导致匹配失败
|
||||||
)
|
const existingPaths = new Set(router.getRoutes().map((r) => r.path))
|
||||||
|
|
||||||
// 🌟 核心:无论什么角色,始终确保首页路由存在
|
// 🌟 核心:无论什么角色,始终确保首页路由存在
|
||||||
if (token && !hasDashboardRoute) {
|
if (!existingPaths.has('/dashboard')) {
|
||||||
router.addRoute('Layout', {
|
router.addRoute('Layout', {
|
||||||
path: '/dashboard',
|
path: '/dashboard',
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
|
|
@ -46,16 +45,16 @@ export const setRouter = () => {
|
||||||
keepAlive: false,
|
keepAlive: false,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
existingPaths.add('/dashboard')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token && menuList.length > 0) {
|
if (menuList.length > 0) {
|
||||||
const routeList = handleRouter(menuList).filter(
|
const routeList = handleRouter(menuList).filter(
|
||||||
(item) => item.path && item.path !== '/dashboard',
|
(item) => item.path && !existingPaths.has(item.path),
|
||||||
)
|
)
|
||||||
routeList.forEach((route) => router.addRoute('Layout', route))
|
routeList.forEach((route) => {
|
||||||
|
router.addRoute('Layout', route)
|
||||||
|
existingPaths.add(route.path)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
router.getRoutes().forEach((route) => {
|
|
||||||
console.log(`路径: ${route.path}, 名称: ${route.name || '无'}`)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -104,25 +104,22 @@ router.beforeEach(async (to, _from) => {
|
||||||
const isLoggedIn = !!userStore.token
|
const isLoggedIn = !!userStore.token
|
||||||
const isRealNameVerified = userStore.userInfo?.real_check !== 1
|
const isRealNameVerified = userStore.userInfo?.real_check !== 1
|
||||||
|
|
||||||
console.log('dynamicRoutesReady', userStore.userInfo)
|
|
||||||
console.log('isLoggedIn', isLoggedIn)
|
|
||||||
console.log('isRealNameVerified', isRealNameVerified)
|
|
||||||
console.log('to.meta.requiresAuth', to.meta.requiresAuth)
|
|
||||||
console.log('to.meta.isAuthPage', to.meta.isAuthPage)
|
|
||||||
|
|
||||||
// 1. 未登录访问需要认证的页 → 登录页
|
// 1. 未登录访问需要认证的页 → 登录页
|
||||||
if (!isLoggedIn && to.meta.requiresAuth) {
|
if (!isLoggedIn && to.meta.requiresAuth) {
|
||||||
return '/user/login'
|
return '/user/login'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ✅ 动态路由恢复(只执行一次)
|
// 2. ✅ 动态路由恢复(只执行一次)
|
||||||
|
// 关键修复:
|
||||||
|
// a) 不要返回 to.redirectedFrom,否则会再次进入守卫形成重入;
|
||||||
|
// b) 返回 next(to.fullPath) 仅在确实新增了路由时触发一次重新匹配;
|
||||||
|
// c) 用动态路由的 pathname 集合做幂等去重,避免同一路由被 addRoute 多次导致匹配失败。
|
||||||
if (isLoggedIn && !dynamicRoutesReady) {
|
if (isLoggedIn && !dynamicRoutesReady) {
|
||||||
const menuList = (getStorage('menusInfo') as any[]) || []
|
const menuList = (getStorage('menusInfo') as any[]) || []
|
||||||
|
|
||||||
// 🌟 核心:无论任何角色,始终确保首页路由存在
|
const existingPaths = new Set(router.getRoutes().map((r) => r.path))
|
||||||
const hasDashboardRoute = router.getRoutes().some(
|
|
||||||
(route) => route.path === '/dashboard',
|
const hasDashboardRoute = existingPaths.has('/dashboard')
|
||||||
)
|
|
||||||
if (!hasDashboardRoute) {
|
if (!hasDashboardRoute) {
|
||||||
router.addRoute('Layout', {
|
router.addRoute('Layout', {
|
||||||
path: '/dashboard',
|
path: '/dashboard',
|
||||||
|
|
@ -135,15 +132,19 @@ router.beforeEach(async (to, _from) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let added = !hasDashboardRoute
|
||||||
if (menuList.length > 0) {
|
if (menuList.length > 0) {
|
||||||
const routeList = handleRouter(menuList).filter(
|
const routeList = handleRouter(menuList).filter(
|
||||||
(item) => item.path && item.path !== '/dashboard',
|
(item) => item.path && item.path !== '/dashboard' && !existingPaths.has(item.path),
|
||||||
)
|
)
|
||||||
routeList.forEach((route) => router.addRoute('Layout', route))
|
routeList.forEach((route) => {
|
||||||
|
router.addRoute('Layout', route)
|
||||||
|
added = true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
dynamicRoutesReady = true
|
dynamicRoutesReady = true
|
||||||
// 返回目标路由以触发重新匹配
|
// 仅当确实新增了路由时才重新匹配目标地址,避免无意义重入
|
||||||
return to.redirectedFrom?.fullPath || true
|
return added ? { path: to.path, query: to.query, hash: to.hash, replace: true } : true
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 白名单页面(实名认证、活体认证、登录/注册相关页面)
|
// 3. 白名单页面(实名认证、活体认证、登录/注册相关页面)
|
||||||
|
|
|
||||||
|
|
@ -337,11 +337,11 @@ const getCustomerList = async (id: string) => {
|
||||||
page_size: pageSize.value,
|
page_size: pageSize.value,
|
||||||
user_name: searchForm.value.accountName,
|
user_name: searchForm.value.accountName,
|
||||||
reg_start_time:
|
reg_start_time:
|
||||||
searchForm.value.startTime.length > 0
|
searchForm.value.startTime?.length > 0
|
||||||
? `${searchForm.value.startTime} 0:00:00`
|
? `${searchForm.value.startTime} 0:00:00`
|
||||||
: '2026-01-01 0:00:00',
|
: '2026-01-01 0:00:00',
|
||||||
reg_end_time:
|
reg_end_time:
|
||||||
searchForm.value.endTime.length > 0
|
searchForm.value.endTime?.length > 0
|
||||||
? `${searchForm.value.endTime} 23:59:59`
|
? `${searchForm.value.endTime} 23:59:59`
|
||||||
: '2026-03-01 23:59:59',
|
: '2026-03-01 23:59:59',
|
||||||
status: searchForm.value.status || '',
|
status: searchForm.value.status || '',
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ const getFundDetailList = async () => {
|
||||||
: '2026-03-15 23:59:59',
|
: '2026-03-15 23:59:59',
|
||||||
user_name: searchForm.value.username,
|
user_name: searchForm.value.username,
|
||||||
account_id: searchForm.value.subAccountId,
|
account_id: searchForm.value.subAccountId,
|
||||||
type: searchForm.value.type,
|
type: searchForm.value.type || '',
|
||||||
}
|
}
|
||||||
// 调用接口获取数据
|
// 调用接口获取数据
|
||||||
const data: any = await getFundDetailListApi(params)
|
const data: any = await getFundDetailListApi(params)
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, computed } from 'vue'
|
import { onMounted, ref, computed, markRaw } from 'vue'
|
||||||
import {
|
import {
|
||||||
UserFilled,
|
UserFilled,
|
||||||
User,
|
User,
|
||||||
|
|
@ -135,13 +135,13 @@ const tagType = computed<'danger' | 'success' | 'warning' | 'primary'>(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const cardData = ref([
|
const cardData = ref([
|
||||||
{ label: '总金额', value: '0', icon: Money },
|
{ label: '总金额', value: '0', icon: markRaw(Money) },
|
||||||
{ label: '盈利', value: '0', icon: Trophy },
|
{ label: '盈利', value: '0', icon: markRaw(Trophy) },
|
||||||
{ label: '手续费佣金', value: '0', icon: Coin },
|
{ label: '手续费佣金', value: '0', icon: markRaw(Coin) },
|
||||||
{ label: '可提现点差佣金', value: '0', icon: Wallet },
|
{ label: '可提现点差佣金', value: '0', icon: markRaw(Wallet) },
|
||||||
{ label: '冻结点差佣金', value: '0', icon: Lock },
|
{ label: '冻结点差佣金', value: '0', icon: markRaw(Lock) },
|
||||||
{ label: '服务费', value: '0', icon: DataAnalysis },
|
{ label: '服务费', value: '0', icon: markRaw(DataAnalysis) },
|
||||||
{ label: '保证金', value: '0', icon: TrendCharts }
|
{ label: '保证金', value: '0', icon: markRaw(TrendCharts) }
|
||||||
])
|
])
|
||||||
|
|
||||||
const quickActions = ref<{ name: string; path: string; icon: any }[]>([])
|
const quickActions = ref<{ name: string; path: string; icon: any }[]>([])
|
||||||
|
|
@ -174,7 +174,7 @@ const initQuickActions = () => {
|
||||||
actions.push({
|
actions.push({
|
||||||
name: child.name || menu.name,
|
name: child.name || menu.name,
|
||||||
path: child.path || '/',
|
path: child.path || '/',
|
||||||
icon: iconMap[child.icon || ''] || List
|
icon: markRaw(iconMap[child.icon || ''] || List)
|
||||||
})
|
})
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|
@ -183,7 +183,7 @@ const initQuickActions = () => {
|
||||||
actions.push({
|
actions.push({
|
||||||
name: menu.name,
|
name: menu.name,
|
||||||
path: menu.path || '/',
|
path: menu.path || '/',
|
||||||
icon: iconMap[menu.icon || ''] || List
|
icon: markRaw(iconMap[menu.icon || ''] || List)
|
||||||
})
|
})
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|
@ -197,13 +197,13 @@ const fetchWalletData = async () => {
|
||||||
const res: any = await getWalletCapital()
|
const res: any = await getWalletCapital()
|
||||||
if (res) {
|
if (res) {
|
||||||
cardData.value = [
|
cardData.value = [
|
||||||
{ label: '总金额', value: res.amount ?? 0, icon: Money },
|
{ label: '总金额', value: res.amount ?? 0, icon: markRaw(Money) },
|
||||||
{ label: '盈利', value: res.closing_profit ?? 0, icon: Trophy },
|
{ label: '盈利', value: res.closing_profit ?? 0, icon: markRaw(Trophy) },
|
||||||
{ label: '手续费佣金', value: res.commission_fee_handling ?? 0, icon: Coin },
|
{ label: '手续费佣金', value: res.commission_fee_handling ?? 0, icon: markRaw(Coin) },
|
||||||
{ label: '可提现点差佣金', value: ((res.commission_point_diff || 0) - (res.freeze || 0)) , icon: Wallet },
|
{ label: '可提现点差佣金', value: ((res.commission_point_diff || 0) - (res.freeze || 0)) , icon: markRaw(Wallet) },
|
||||||
{ label: '冻结点差佣金', value: res.freeze ?? 0, icon: Lock },
|
{ label: '冻结点差佣金', value: res.freeze ?? 0, icon: markRaw(Lock) },
|
||||||
{ label: '服务费', value: res.service ?? 0, icon: DataAnalysis },
|
{ label: '服务费', value: res.service ?? 0, icon: markRaw(DataAnalysis) },
|
||||||
{ label: '保证金', value: res.bail ?? 0, icon: TrendCharts }
|
{ label: '保证金', value: res.bail ?? 0, icon: markRaw(TrendCharts) }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted, watch } from 'vue'
|
import { ref, computed, onMounted, watch, markRaw } from 'vue'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import {
|
import {
|
||||||
Check,
|
Check,
|
||||||
|
|
@ -345,7 +345,7 @@ const quickActions = ref([
|
||||||
title: '存款',
|
title: '存款',
|
||||||
desc: '安全便捷的充值服务',
|
desc: '安全便捷的充值服务',
|
||||||
path: '/capital/rechange',
|
path: '/capital/rechange',
|
||||||
icon: CircleCheckFilled,
|
icon: markRaw(CircleCheckFilled),
|
||||||
bgColor: 'linear-gradient(135deg, #e6f4ff 0%, #bae0ff 100%)',
|
bgColor: 'linear-gradient(135deg, #e6f4ff 0%, #bae0ff 100%)',
|
||||||
iconColor: '#165DFF'
|
iconColor: '#165DFF'
|
||||||
},
|
},
|
||||||
|
|
@ -354,7 +354,7 @@ const quickActions = ref([
|
||||||
title: '取款',
|
title: '取款',
|
||||||
desc: '快速到账资金提取',
|
desc: '快速到账资金提取',
|
||||||
path: '/capital/withdraw',
|
path: '/capital/withdraw',
|
||||||
icon: Money,
|
icon: markRaw(Money),
|
||||||
bgColor: 'linear-gradient(135deg, #f6ffed 0%, #d9f7be 100%)',
|
bgColor: 'linear-gradient(135deg, #f6ffed 0%, #d9f7be 100%)',
|
||||||
iconColor: '#52c41a'
|
iconColor: '#52c41a'
|
||||||
},
|
},
|
||||||
|
|
@ -363,7 +363,7 @@ const quickActions = ref([
|
||||||
title: '交易',
|
title: '交易',
|
||||||
desc: '全球金融产品交易',
|
desc: '全球金融产品交易',
|
||||||
path: '/trade/exe',
|
path: '/trade/exe',
|
||||||
icon: TrendCharts,
|
icon: markRaw(TrendCharts),
|
||||||
bgColor: 'linear-gradient(135deg, #fff7e6 0%, #ffd591 100%)',
|
bgColor: 'linear-gradient(135deg, #fff7e6 0%, #ffd591 100%)',
|
||||||
iconColor: '#fa8c16'
|
iconColor: '#fa8c16'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onMounted, ref, computed } from 'vue'
|
import { onMounted, ref, computed, markRaw } from 'vue'
|
||||||
import { UserFilled, User, TrendCharts, Money, Wallet, Coin, Timer, Operation, Right, List, Goods, Document, Setting } from '@element-plus/icons-vue'
|
import { UserFilled, User, TrendCharts, Money, Wallet, Coin, Timer, Operation, Right, List, Goods, Document, Setting } from '@element-plus/icons-vue'
|
||||||
import Agent from './components/view/index.vue'
|
import Agent from './components/view/index.vue'
|
||||||
import MarketMakerDashboard from './components/marketMaker/index.vue'
|
import MarketMakerDashboard from './components/marketMaker/index.vue'
|
||||||
|
|
@ -114,13 +114,13 @@ const formattedDate = computed(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const cardData = ref([
|
const cardData = ref([
|
||||||
{ label: '代理总数', value: 0, icon: UserFilled },
|
{ label: '代理总数', value: 0, icon: markRaw(UserFilled) },
|
||||||
{ label: '用户总数', value: 0, icon: User },
|
{ label: '用户总数', value: 0, icon: markRaw(User) },
|
||||||
{ label: '今日新增用户', value: 0, icon: TrendCharts },
|
{ label: '今日新增用户', value: 0, icon: markRaw(TrendCharts) },
|
||||||
{ label: '今日充值金额', value: '0', icon: Money },
|
{ label: '今日充值金额', value: '0', icon: markRaw(Money) },
|
||||||
{ label: '今日提现金额', value: 0, icon: Wallet },
|
{ label: '今日提现金额', value: 0, icon: markRaw(Wallet) },
|
||||||
{ label: '总充值金额', value: 0, icon: Coin },
|
{ label: '总充值金额', value: 0, icon: markRaw(Coin) },
|
||||||
{ label: '总提现金额', value: 0, icon: Timer }
|
{ label: '总提现金额', value: 0, icon: markRaw(Timer) }
|
||||||
])
|
])
|
||||||
|
|
||||||
const quickActions = ref<{ name: string; path: string; icon: any }[]>([])
|
const quickActions = ref<{ name: string; path: string; icon: any }[]>([])
|
||||||
|
|
@ -153,7 +153,7 @@ const initQuickActions = () => {
|
||||||
actions.push({
|
actions.push({
|
||||||
name: child.name || menu.name,
|
name: child.name || menu.name,
|
||||||
path: child.path || '/',
|
path: child.path || '/',
|
||||||
icon: iconMap[child.icon || ''] || List
|
icon: markRaw(iconMap[child.icon || ''] || List)
|
||||||
})
|
})
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|
@ -162,7 +162,7 @@ const initQuickActions = () => {
|
||||||
actions.push({
|
actions.push({
|
||||||
name: menu.name,
|
name: menu.name,
|
||||||
path: menu.path || '/',
|
path: menu.path || '/',
|
||||||
icon: iconMap[menu.icon || ''] || List
|
icon: markRaw(iconMap[menu.icon || ''] || List)
|
||||||
})
|
})
|
||||||
count++
|
count++
|
||||||
}
|
}
|
||||||
|
|
@ -179,13 +179,13 @@ const fetchDashboardData = async () => {
|
||||||
today_withdraw_amount, total_recharge_amount, total_withdraw_amount } = res
|
today_withdraw_amount, total_recharge_amount, total_withdraw_amount } = res
|
||||||
|
|
||||||
cardData.value = [
|
cardData.value = [
|
||||||
{ label: '代理总数', value: agent_count, icon: UserFilled },
|
{ label: '代理总数', value: agent_count, icon: markRaw(UserFilled) },
|
||||||
{ label: '用户总数', value: user_count, icon: User },
|
{ label: '用户总数', value: user_count, icon: markRaw(User) },
|
||||||
{ label: '今日新增用户', value: today_user_count, icon: TrendCharts },
|
{ label: '今日新增用户', value: today_user_count, icon: markRaw(TrendCharts) },
|
||||||
{ label: '今日充值金额', value: today_recharge_amount, icon: Money },
|
{ label: '今日充值金额', value: today_recharge_amount, icon: markRaw(Money) },
|
||||||
{ label: '今日提现金额', value: today_withdraw_amount, icon: Wallet },
|
{ label: '今日提现金额', value: today_withdraw_amount, icon: markRaw(Wallet) },
|
||||||
{ label: '总充值金额', value: total_recharge_amount, icon: Coin },
|
{ label: '总充值金额', value: total_recharge_amount, icon: markRaw(Coin) },
|
||||||
{ label: '总提现金额', value: total_withdraw_amount, icon: Timer }
|
{ label: '总提现金额', value: total_withdraw_amount, icon: markRaw(Timer) }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -206,7 +206,7 @@ onMounted(() => {
|
||||||
.dashboard {
|
.dashboard {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
// max-width: 1600px;
|
// max-width: 1600px;
|
||||||
margin: 0 auto;
|
// margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-header {
|
.page-header {
|
||||||
|
|
|
||||||
|
|
@ -90,12 +90,12 @@ const getCustomerTradeOrderList = async () => {
|
||||||
const params = {
|
const params = {
|
||||||
page: currentPage.value,
|
page: currentPage.value,
|
||||||
page_size: pageSize.value,
|
page_size: pageSize.value,
|
||||||
user_name: searchForm.value.accountName,
|
user_name: searchForm.value.accountName || '',
|
||||||
account_id: searchForm.value.subAccountName || '',
|
account_id: searchForm.value.subAccountName || '',
|
||||||
order_no: '',
|
order_no: '',
|
||||||
type: searchForm.value.tradeType,
|
type: searchForm.value.tradeType || '',
|
||||||
start_time: startTime,
|
start_time: startTime || '',
|
||||||
end_time: endTime,
|
end_time: endTime || '',
|
||||||
}
|
}
|
||||||
console.log(params)
|
console.log(params)
|
||||||
const data: any = await getCustomTradeOrderListApi(params)
|
const data: any = await getCustomTradeOrderListApi(params)
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,29 @@
|
||||||
|
import { markRaw } from 'vue'
|
||||||
import { Tools, List, HomeFilled, UserFilled, Platform, BellFilled, GoodsFilled, WarningFilled } from '@element-plus/icons-vue'
|
import { Tools, List, HomeFilled, UserFilled, Platform, BellFilled, GoodsFilled, WarningFilled } from '@element-plus/icons-vue'
|
||||||
|
|
||||||
// 定义图标映射表配置
|
// 定义图标映射表配置
|
||||||
export const menuiconMap: Record<string, any> = {
|
export const menuiconMap: Record<string, any> = {
|
||||||
Tools,
|
Tools: markRaw(Tools),
|
||||||
List,
|
List: markRaw(List),
|
||||||
HomeFilled,
|
HomeFilled: markRaw(HomeFilled),
|
||||||
UserFilled,
|
UserFilled: markRaw(UserFilled),
|
||||||
Platform,
|
Platform: markRaw(Platform),
|
||||||
BellFilled,
|
BellFilled: markRaw(BellFilled),
|
||||||
GoodsFilled,
|
GoodsFilled: markRaw(GoodsFilled),
|
||||||
WarningFilled
|
WarningFilled: markRaw(WarningFilled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义选择图标选项列表配置
|
// 定义选择图标选项列表配置
|
||||||
export const menuiconOptions = [
|
export const menuiconOptions = [
|
||||||
{ label: "无图标", value: "无图标" },
|
{ label: "无图标", value: "无图标" },
|
||||||
{ label: "Tools(工具)", value: "Tools", icon: Tools },
|
{ label: "Tools(工具)", value: "Tools", icon: markRaw(Tools) },
|
||||||
{ label: "List(列表)", value: "List", icon: List },
|
{ label: "List(列表)", value: "List", icon: markRaw(List) },
|
||||||
{ label: "HomeFilled(首页)", value: "HomeFilled", icon: HomeFilled },
|
{ label: "HomeFilled(首页)", value: "HomeFilled", icon: markRaw(HomeFilled) },
|
||||||
{ label: "UserFilled(用户)", value: "UserFilled", icon: UserFilled },
|
{ label: "UserFilled(用户)", value: "UserFilled", icon: markRaw(UserFilled) },
|
||||||
{ label: "Platform(平台)", value: "Platform", icon: Platform },
|
{ label: "Platform(平台)", value: "Platform", icon: markRaw(Platform) },
|
||||||
{ label: "BellFilled(铃铛)", value: "BellFilled", icon: BellFilled },
|
{ label: "BellFilled(铃铛)", value: "BellFilled", icon: markRaw(BellFilled) },
|
||||||
{ label: "GoodsFilled(商品)", value: "GoodsFilled", icon: GoodsFilled },
|
{ label: "GoodsFilled(商品)", value: "GoodsFilled", icon: markRaw(GoodsFilled) },
|
||||||
{ label: "WarningFilled(警告)", value: "WarningFilled", icon: WarningFilled },
|
{ label: "WarningFilled(警告)", value: "WarningFilled", icon: markRaw(WarningFilled) },
|
||||||
]
|
]
|
||||||
|
|
||||||
//定义table配置
|
//定义table配置
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,18 @@
|
||||||
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
|
<el-option v-for="item in typeList" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
|
<template #tradeStatus>
|
||||||
|
<el-select v-model="searchForm.tradeStatus" placeholder="请选择状态" clearable style="width: 200px;">
|
||||||
|
<el-option :value="1" label="开启" />
|
||||||
|
<el-option :value="2" label="禁用" />
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
<template #onlineStatus>
|
||||||
|
<el-select v-model="searchForm.onlineStatus" placeholder="请选择上线状态" clearable style="width: 200px;">
|
||||||
|
<el-option :value="1" label="上线" />
|
||||||
|
<el-option :value="2" label="下线" />
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
<template #button="{ form }">
|
<template #button="{ form }">
|
||||||
<el-button type="primary" :disabled="!selectedRow" @click="handleEdit()" v-auth="'contractVariety_editVariety'">
|
<el-button type="primary" :disabled="!selectedRow" @click="handleEdit()" v-auth="'contractVariety_editVariety'">
|
||||||
编辑
|
编辑
|
||||||
|
|
@ -103,7 +115,9 @@ import { uploadImageApi } from '@/api/modules/upload'
|
||||||
*/
|
*/
|
||||||
const searchForm = ref({
|
const searchForm = ref({
|
||||||
varietyName: '',
|
varietyName: '',
|
||||||
type:''
|
type:'',
|
||||||
|
tradeStatus: '',
|
||||||
|
onlineStatus: '',
|
||||||
})
|
})
|
||||||
const searchOptions = ref(search)
|
const searchOptions = ref(search)
|
||||||
|
|
||||||
|
|
@ -235,6 +249,8 @@ const getVarietyList = async () => {
|
||||||
const params = {
|
const params = {
|
||||||
name: searchForm.value.varietyName,
|
name: searchForm.value.varietyName,
|
||||||
type: searchForm.value.type,
|
type: searchForm.value.type,
|
||||||
|
online_status: searchForm.value.onlineStatus || '',
|
||||||
|
status: searchForm.value.tradeStatus || ''
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const data = await getVarietyListApi(params)
|
const data = await getVarietyListApi(params)
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ export const search = [
|
||||||
// 品种名称
|
// 品种名称
|
||||||
{ prop: 'varietyName', label: '品种名称', type: 'input' as const, placeholder: '请输入品种名称' },
|
{ prop: 'varietyName', label: '品种名称', type: 'input' as const, placeholder: '请输入品种名称' },
|
||||||
{ prop: 'type', label: '类型', type: 'select' as const, placeholder: '请选择类型', slot: true, },
|
{ prop: 'type', label: '类型', type: 'select' as const, placeholder: '请选择类型', slot: true, },
|
||||||
|
{ prop: 'tradeStatus', label: '状态', type: 'select' as const, placeholder: '请选择状态', slot: true, },
|
||||||
|
{ prop: 'onlineStatus', label: '上线状态', type: 'select' as const, placeholder: '请选择上线状态', slot: true, },
|
||||||
]
|
]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="user-container">
|
<router-view v-slot="{ Component }">
|
||||||
<router-view v-slot="{ Component }">
|
<transition name="user" mode="out-in">
|
||||||
<transition name="user" mode="out-in">
|
<div class="user-container">
|
||||||
<component :is="Component" />
|
<component :is="Component" />
|
||||||
</transition>
|
</div>
|
||||||
</router-view>
|
</transition>
|
||||||
</div>
|
</router-view>
|
||||||
</template>
|
</template>
|
||||||
Loading…
Reference in New Issue