处理加载

This commit is contained in:
2026-05-21 09:14:36 +08:00
parent 955f85eac8
commit 3a23a85077
28 changed files with 354 additions and 125 deletions

View File

@ -1,8 +1,21 @@
<template>
<div class="app-container">
<TopLoading ref="topLoadingRef" />
<KeepAlive>
<router-view></router-view>
</KeepAlive>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import TopLoading from '@/components/common/TopLoading.vue'
const topLoadingRef = ref<InstanceType<typeof TopLoading>>()
onMounted(() => {
// TopLoading window api
// @ts-ignore
window.__topLoading__ = topLoadingRef.value
})
</script>

View File

@ -1,35 +1,33 @@
import axios from 'axios'
import type { AxiosResponse, AxiosError, InternalAxiosRequestConfig } from 'axios'
import type { ApiResponse } from '@/api/types'
import { ElLoading, ElNotification } from 'element-plus'
import { ElNotification } from 'element-plus'
import { getStorage, setStorage, removeStorage } from '@/utils/storage'
import router from '../router'
// 定义loading实例类型用于控制loading的显示和关闭
let loadingInstance: ReturnType<typeof ElLoading.service> | null = null
// 记录当前请求数量,防止多个请求重复显示/关闭loading
// 记录当前请求数量,用于控制顶部进度条
let requestCount = 0
// 显示loading的方法
// 获取 TopLoading 实例
const getTopLoading = () => {
// @ts-ignore
return window.__topLoading__
}
// 显示顶部进度条
const showLoading = () => {
if (requestCount === 0 && !loadingInstance) {
loadingInstance = ElLoading.service({
lock: true, // 锁定屏幕滚动
fullscreen: true, // 全屏显示
})
if (requestCount === 0) {
getTopLoading()?.start()
}
requestCount++
}
// 关闭loading的方法
// 关闭顶部进度条
const hideLoading = () => {
requestCount--
if (requestCount <= 0) {
if (loadingInstance) {
loadingInstance.close()
loadingInstance = null
}
requestCount = 0 // 重置计数,防止负数
getTopLoading()?.complete()
requestCount = 0
}
}
@ -49,10 +47,8 @@ const service = axios.create({
const requestInterceptor = (config: InternalAxiosRequestConfig) => {
console.log('请求配置', config)
// 显示loading可通过config配置项控制是否显示比如某些请求不需要loading
if (config.headers?.showLoading !== false) {
showLoading()
}
// 显示顶部进度条
showLoading()
// 添加token到请求头
const token = getStorage('token')
if (token) {

View File

@ -8,6 +8,7 @@
:tree-props="treeProps"
:border="border"
:highlight-current-row="highlightCurrentRow"
v-loading="loading"
v-bind="$attrs"
@row-click="handleRowClick"
@row-contextmenu="handleRowContextmenu"
@ -71,11 +72,13 @@ interface Props {
columns?: TableColumn[]
border?: boolean //
highlightCurrentRow?: boolean //
loading?: boolean //
}
const props = withDefaults(defineProps<Props>(), {
border: true,
highlightCurrentRow: true,
loading: false,
})
//

View File

@ -0,0 +1,62 @@
<template>
<Teleport to="body">
<div v-if="visible" class="top-loading-bar">
<div class="loading-progress" :style="{ width: progress + '%' }"></div>
</div>
</Teleport>
</template>
<script setup lang="ts">
import { ref } from 'vue'
const visible = ref(false)
const progress = ref(0)
let timer: ReturnType<typeof setInterval> | null = null
const start = () => {
visible.value = true
progress.value = 0
// 90%
timer = setInterval(() => {
if (progress.value < 90) {
progress.value += Math.random() * 15 + 5
}
}, 150)
}
const complete = () => {
if (timer) {
clearInterval(timer)
timer = null
}
progress.value = 100
setTimeout(() => {
visible.value = false
progress.value = 0
}, 200)
}
//
defineExpose({
start,
complete,
})
</script>
<style scoped lang="scss">
.top-loading-bar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
z-index: 9999;
background: transparent;
}
.loading-progress {
height: 100%;
background: #409eff; // Element Plus
transition: width 0.15s linear;
}
</style>

View File

@ -11,7 +11,7 @@
<!-- 右侧内容区页签 + 主体内容 -->
<section class="content-container">
<!-- 页签标签栏 -->
<!-- <Tabs /> -->
<Tabs />
<!-- 主体内容区 -->
<main class="main-content">

View File

@ -0,0 +1,44 @@
import { ref } from 'vue'
/**
*
* @param initialLoading loading false
*/
export function usePageLoading(initialLoading = false) {
const loading = ref(initialLoading)
const startLoading = () => {
loading.value = true
}
const stopLoading = () => {
loading.value = false
}
return {
loading,
startLoading,
stopLoading,
}
}
/**
*
*/
export function useButtonLoading() {
const buttonLoading = ref(false)
const startButtonLoading = () => {
buttonLoading.value = true
}
const stopButtonLoading = () => {
buttonLoading.value = false
}
return {
buttonLoading,
startButtonLoading,
stopButtonLoading,
}
}

View File

@ -6,7 +6,7 @@
<!-- 表格 -->
<CustomerListTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="userId" :tree-props="treeProps"
:default-sort="{ prop: 'createTime', order: 'descending' }" @expand-change="handleGetSubList">
:default-sort="{ prop: 'createTime', order: 'descending' }" :loading="loading" @expand-change="handleGetSubList">
<template #marginRatio="{ row }">
<el-button v-if="row.role_id === 5" type="primary" size="small" @click="handleMarginRatio(row)">
修改
@ -126,6 +126,7 @@ defineOptions({
//
import CustomerListSearch from '@/components/common/Search.vue'
import CustomerListTable from '@/components/common/Table.vue'
import { usePageLoading } from '@/composables/useLoading'
import CustomerListPagination from '@/components/common/Pagination.vue'
import CustomerListDialog from '@/components/common/Dialog.vue'
import CustomerListForm from '@/components/common/Form.vue'
@ -170,6 +171,7 @@ const searchForm = ref({
const searchOptions = ref(search)
const tableColumnsOptions = ref(tableColumns)
const { loading, startLoading, stopLoading } = usePageLoading()
/**
* @description: 定义表格数据
*/
@ -323,6 +325,7 @@ const roleMap: any = {
*/
//
const getCustomerList = async (id: string) => {
startLoading()
const params = {
user_id: id,
page: currentPage.value,
@ -360,6 +363,7 @@ const getCustomerList = async (id: string) => {
}))
console.log('tableTree', tableTree.value)
//
stopLoading()
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)

View File

@ -4,7 +4,7 @@
<FundDetailHeader title="入金货币" :buttons="buttonsOptions" @button-click="handleButtonClick">
</FundDetailHeader>
<!-- 表格 -->
<FundDetailTable :table-data="tableData" :columns="tableColumnsOptions" @row-click="handleRowClick" row-key="id" />
<FundDetailTable :table-data="tableData" :columns="tableColumnsOptions" @row-click="handleRowClick" row-key="id" :loading="loading" />
<FundDetailDialog :visible="visible" :title="dialogTitle" @close="visible = false" @cancel="visible = false"
@confirm="handleConfirm">
<FundDetailForm :formData="formData" :formItems="formItems" :formRules="formRules" :optionsMap="optionsMap">
@ -20,6 +20,7 @@ defineOptions({
})
import FundDetailHeader from '@/components/common/header.vue'
import FundDetailTable from '@/components/common/Table.vue'
import { usePageLoading } from '@/composables/useLoading'
import FundDetailDialog from '@/components/common/Dialog.vue'
import FundDetailForm from '@/components/common/Form.vue'
import type { ButtonProps } from 'element-plus'
@ -41,6 +42,7 @@ interface HeaderButton {
key?: string | number //
}
const { loading, startLoading, stopLoading } = usePageLoading()
const buttonsOptions = ref(buttons)
const formItems = ref(form)
const tableData = ref([])
@ -70,7 +72,9 @@ let rowData: any = {}
const visible = ref<boolean>(false)
const getTableList = async () => {
startLoading()
const data = await getCurrencyList()
stopLoading()
tableData.value = (data || []).map((item: any) => {
return {
...item,

View File

@ -12,7 +12,7 @@
</template>
</FundDetailSearch>
<!-- 表格 -->
<FundDetailTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="id" />
<FundDetailTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="id" :loading="loading" />
<!-- 分页 -->
<FundDetailPagination
v-model="currentPage"
@ -32,6 +32,7 @@ defineOptions({
import FundDetailSearch from '@/components/common/Search.vue'
import FundDetailTable from '@/components/common/Table.vue'
import FundDetailPagination from '@/components/common/Pagination.vue'
import { usePageLoading } from '@/composables/useLoading'
//
import { search, tableColumns } from './options'
//
@ -51,6 +52,7 @@ const searchForm = ref({
startTime: initTime.start,
endTime: initTime.end,
})
const { loading, startLoading, stopLoading } = usePageLoading()
/**
* @description: 定义表格数据
*/
@ -68,6 +70,7 @@ const total = ref(0)
*/
//
const getFundDetailList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
@ -84,6 +87,7 @@ const getFundDetailList = async () => {
}
//
const data: any = await getFundDetailListApi(params)
stopLoading()
console.log(data)
tableTree.value = data.data.map((item: any) => ({
...item,

View File

@ -4,7 +4,7 @@
<div class="page-title">存款</div>
<!-- 存款渠道列表每行提供一个"存款"按钮 -->
<RechangeTable :table-data="channelList" :columns="tableColumns" :highlight-current-row="false">
<RechangeTable :table-data="channelList" :columns="tableColumns" :highlight-current-row="false" :loading="loading">
<template #action="{ row }">
<el-button type="primary" size="small" @click="handleOpenDialog(row)">
存款
@ -113,6 +113,7 @@ import { ElMessage } from 'element-plus'
import { nextTick, onMounted, ref } from 'vue'
import RechangeTable from '@/components/common/Table.vue'
import RechangeDialog from '@/components/common/Dialog.vue'
import { usePageLoading } from '@/composables/useLoading'
import { rechangeTableColumns } from './options'
import { uploadImageApi } from '@/api/modules/upload'
import { getRechargeChannelList, rechargeApi } from '@/api/modules/capital/rechangeChanl'
@ -151,6 +152,7 @@ const submitLoading = ref(false)
const voucherUrl = ref('')
const uploadLoading = ref(false)
const { loading, startLoading, stopLoading } = usePageLoading()
//
const channelList = ref<ChannelRow[]>([])
@ -202,10 +204,13 @@ const rechangeFormRules = ref<FormRules<RechangeFormData>>({
//
const fetchChannelList = async () => {
startLoading()
try {
const res = await getRechargeChannelList() as ChannelRow[]
stopLoading()
channelList.value = res || []
} catch (error) {
stopLoading()
console.error('获取充值渠道列表失败', error)
}
}

View File

@ -10,6 +10,7 @@
:table-data="tableData"
:columns="tableColumnsOptions"
row-key="id"
:loading="loading"
@rowClick="handleRowClick"
/>
<el-dialog
@ -40,6 +41,7 @@ defineOptions({
//
import DepositChannelTable from '@/components/common/Table.vue'
import Form from '@/components/common/Form.vue'
import { usePageLoading } from '@/composables/useLoading'
import { tableColumns, formItemsData, formRulesData, optionsMapData } from './options'
import {
getChannelList,
@ -65,8 +67,11 @@ const getStatusText = (status: number | string) => {
return ['', '正常', '禁用'][status]
}
const { loading, startLoading, stopLoading } = usePageLoading()
const initData = async () => {
startLoading()
const res = await getChannelList()
stopLoading()
console.log(res)
tableData.value = res.map((item: ChannelType) => ({
...item,

View File

@ -68,6 +68,7 @@ defineOptions({
import { ElMessage } from 'element-plus'
import { onMounted, ref } from 'vue'
import RechangeSearch from '@/components/common/Search.vue'
import { usePageLoading } from '@/composables/useLoading'
import RechangePagination from '@/components/common/Pagination.vue'
import { exportToExcel } from '@/utils/exportToExcel'
import { getRechargeCheckListApi, reviewRechargeOrder } from '@/api/modules/capital/rechargeCheck'
@ -101,10 +102,10 @@ interface SearchFormData {
const searchOptions = ref(rechangeCheckSearch)
const tableColumns = ref(rechangeCheckTableColumns)
const { loading, startLoading, stopLoading } = usePageLoading()
// loading
const tableData = ref<TableRow[]>([])
const selectedRows = ref<TableRow[]>([])
const loading = ref(false)
//
const total = ref(0)
@ -137,7 +138,7 @@ const getRechargeStatusText = (status: string | number | null | undefined) => {
// page / page_size / start_time / end_time null
const getList = async () => {
loading.value = true
startLoading()
selectedRows.value = []
const params = {
@ -175,7 +176,7 @@ const getList = async () => {
total.value = 0
console.error('获取充值审核列表失败', error)
} finally {
loading.value = false
stopLoading()
}
}

View File

@ -5,7 +5,7 @@
:table-data="tableData"
:columns="tableColumnsOptions"
row-key="id"
v-loading="tableLoading"
:loading="loading"
@rowClick="handleRowClick"
>
<template #action="{ row }">
@ -33,6 +33,7 @@ import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import Table from '@/components/common/Table.vue'
import Pagination from '@/components/common/Pagination.vue'
import { usePageLoading } from '@/composables/useLoading'
import WithdrawDialog from './components/WithdrawDialog.vue'
import { tableColumns } from './options'
import { getWithdrawChannel } from '@/api/modules/capital/withdraw'
@ -54,7 +55,7 @@ interface TableRow {
const tableRef = ref()
const tableData = ref<TableRow[]>([])
const tableLoading = ref(false)
const { loading, startLoading, stopLoading } = usePageLoading()
const total = ref(0)
const withdrawDialogVisible = ref(false)
const currentChannelId = ref<number>()
@ -70,7 +71,7 @@ const tableColumnsOptions = tableColumns
//
const getList = async () => {
tableLoading.value = true
startLoading()
try {
const res: any = await getWithdrawChannel()
if (res) {
@ -83,7 +84,7 @@ const getList = async () => {
} catch (error) {
console.error('获取列表失败', error)
} finally {
tableLoading.value = false
stopLoading()
}
}

View File

@ -10,6 +10,7 @@
:table-data="tableData"
:columns="tableColumnsOptions"
row-key="id"
:loading="loading"
@rowClick="handleRowClick"
/>
<el-dialog
@ -39,6 +40,7 @@ defineOptions({
//
import Table from '@/components/common/Table.vue'
import Form from '@/components/common/Form.vue'
import { usePageLoading } from '@/composables/useLoading'
import { tableColumns, formItemsData, formRulesData, optionsMapData } from './options'
import {
getChannelWithdrawList,
@ -65,8 +67,11 @@ const getStatusText = (status: number | string) => {
return ['', '正常', '禁用'][status]
}
const { loading, startLoading, stopLoading } = usePageLoading()
const initData = async () => {
startLoading()
const res = await getChannelWithdrawList()
stopLoading()
console.log(res)
tableData.value = res.map((item: ChannelType) => ({
...item,

View File

@ -43,6 +43,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { computed, onMounted, ref } from 'vue'
import dayjs from 'dayjs'
import WithdrawSearch from '@/components/common/Search.vue'
import { usePageLoading } from '@/composables/useLoading'
import WithdrawPagination from '@/components/common/Pagination.vue'
import { withdrawCheckSearch, withdrawCheckTableColumns } from './options'
import { getWithdrawReviewList, withdrawReviewOrder } from '@/api/modules/capital/withdraw'
@ -117,11 +118,11 @@ const searchForm = ref({
timeRange: [] as string[]
})
const { loading, startLoading, stopLoading } = usePageLoading()
// loading
const tableColumns = computed(() => withdrawCheckTableColumns)
const tableData = ref<TransformedTableRow[]>([])
const selectedRows = ref<TableRow[]>([])
const loading = ref(false)
// loading
const approveLoading = ref(false)
@ -172,7 +173,7 @@ interface ListResponse {
//
const getList = async () => {
loading.value = true
startLoading()
selectedRows.value = []
const [start_time, end_time] = searchForm.value.timeRange || []
@ -192,7 +193,7 @@ const getList = async () => {
console.error('获取提现审核列表失败:', error)
ElMessage.error('获取列表失败')
} finally {
loading.value = false
stopLoading()
}
}

View File

@ -28,6 +28,7 @@
highlight-current-row
border
@current-change="handleCurrentChange"
:loading="loading"
>
<el-table-column type="index" width="55" />
<el-table-column
@ -39,7 +40,7 @@
</el-table>
</div>
<div class="table-container-right">
<el-table height="100%" :data="tableDataDetail">
<el-table height="100%" :data="tableDataDetail" :loading="loading">
<el-table-column
v-for="column in tableColumnsDetail"
:key="column.prop"
@ -94,6 +95,9 @@ defineOptions({
name: 'HandleFee'
})
import { ref, onMounted } from 'vue'
import { usePageLoading } from '@/composables/useLoading'
const { loading, startLoading, stopLoading } = usePageLoading()
import {
getFeeSettingList,
getFeeSettingDetail,
@ -146,19 +150,24 @@ const tableColumnsDetail = ref([
])
const getTableData = async () => {
const res = await getFeeSettingList()
const savedId = currentRow.value?.id
tableData.value = res
console.log(res)
if (res && res.length > 0) {
const targetRow = savedId ? res.find((item: any) => item.id === savedId) : null
if (targetRow) {
setCurrent(targetRow)
handleCurrentChange(targetRow)
} else {
setCurrent(res[0])
handleCurrentChange(res[0])
startLoading()
try {
const res = await getFeeSettingList()
const savedId = currentRow.value?.id
tableData.value = res
console.log(res)
if (res && res.length > 0) {
const targetRow = savedId ? res.find((item: any) => item.id === savedId) : null
if (targetRow) {
setCurrent(targetRow)
handleCurrentChange(targetRow)
} else {
setCurrent(res[0])
handleCurrentChange(res[0])
}
}
} finally {
stopLoading()
}
}

View File

@ -34,6 +34,7 @@
row-key="id"
highlight-current-row
:current-row-key="selectedRowId"
:loading="loading"
>
<template #status="{ row }">
<span>{{ row.status === 1 ? '启用' : '停用' }}</span>
@ -44,6 +45,7 @@
:table-data="currentContent"
class="table-content"
row-key="id"
:loading="loading"
>
</RiskTableContent>
</div>
@ -75,6 +77,9 @@ defineOptions({
name: 'Risk'
})
//
import { usePageLoading } from '@/composables/useLoading'
const { loading, startLoading, stopLoading } = usePageLoading()
import RiskTableSwitch from '@/components/common/Table.vue'
import RiskTableContent from '@/components/common/Table.vue'
import RiskDialog from '@/components/common/Dialog.vue'
@ -165,39 +170,41 @@ const colSpan = ref(12)
* @description: 定义请求数据方法
*/
const getRiskList = async () => {
const data: any = await getRiskListApi()
//
riskOriginData.value = data
//
tableTreeSwitch.value = data.map((item: any) => ({
id: item.id,
name: item.name,
status: item.status,
}))
tableTreeContent.value = data.map((item: any) => ({
id: item.id,
isDefault: item.is_default,
//
maxOpenPosition: item.max_opening_quantity_per_transaction,
//
maxPositionPerSymbol: item.max_holding_quantity_per_variety,
//
maxTotalPosition: item.max_holding_quantity_per_transaction,
//
strongCloseRatio: item.strong_to_average_ratio,
//
maxWithdrawalAmount: item.max_withdrawal_amount_per_transaction,
//
isWithdrawalAllowed: item.withdraw_status === 1 ? '是' : '否',
//
withdrawalTimeSetting: item.withdraw_time,
//
isWithdrawalAuditRequired: item.withdraw_is_check === 1 ? '是' : '否',
//
buildCloseTime: item.open_close_time,
//
minWithdrawalAmount: item.min_withdrawal_amount_per_transaction,
//
startLoading()
const data: any = await getRiskListApi()
stopLoading()
//
riskOriginData.value = data
//
tableTreeSwitch.value = data.map((item: any) => ({
id: item.id,
name: item.name,
status: item.status,
}))
tableTreeContent.value = data.map((item: any) => ({
id: item.id,
isDefault: item.is_default,
//
maxOpenPosition: item.max_opening_quantity_per_transaction,
//
maxPositionPerSymbol: item.max_holding_quantity_per_variety,
//
maxTotalPosition: item.max_holding_quantity_per_transaction,
//
strongCloseRatio: item.strong_to_average_ratio,
//
maxWithdrawalAmount: item.max_withdrawal_amount_per_transaction,
//
isWithdrawalAllowed: item.withdraw_status === 1 ? '是' : '否',
//
withdrawalTimeSetting: item.withdraw_time,
//
isWithdrawalAuditRequired: item.withdraw_is_check === 1 ? '是' : '否',
//
buildCloseTime: item.open_close_time,
//
minWithdrawalAmount: item.min_withdrawal_amount_per_transaction,
//
slippage: item.slippage,
//
minDepositAmount: item.min_recharge_amount_per_transaction,

View File

@ -10,7 +10,7 @@
<div>交易盈亏:0.00 USD</div>
</div>
<!-- 表格 -->
<CustomerTradeOrderTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="id" />
<CustomerTradeOrderTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="id" :loading="loading" />
<!-- 分页 -->
<CustomerTradeOrderPagination v-model="currentPage" v-model:pageSizeValue="pageSize" :total="total"
@ -27,6 +27,7 @@ defineOptions({
//
import CustomerTradeOrderSearch from '@/components/common/Search.vue'
import CustomerTradeOrderTable from '@/components/common/Table.vue'
import { usePageLoading } from '@/composables/useLoading'
import CustomerTradeOrderPagination from '@/components/common/Pagination.vue'
//
import { search, tradeOrderTableColumns, positionOrderTableColumns } from './options'
@ -63,6 +64,7 @@ const subAccountOptions = ref([])
//
const userInfo: any = getStorage('userInfo')
const { loading, startLoading, stopLoading } = usePageLoading()
/**
* @description: 定义表格数据
*/
@ -80,6 +82,7 @@ const total = ref(0)
* @description: 定义公共请求数据方法
*/
const getCustomerTradeOrderList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
@ -92,7 +95,7 @@ const getCustomerTradeOrderList = async () => {
}
console.log(params)
const data: any = await getCustomTradeOrderListApi(params)
stopLoading()
//
// table
tableTree.value = data.data.map((item: any) => ({

View File

@ -13,6 +13,7 @@
:table-data="tableTree"
:columns="tableColumnsOptions"
:highlight-current-row="false"
:loading="loading"
>
<!-- 操作列插槽 -->
<!-- <template #operation="{ row }">-->
@ -43,6 +44,7 @@ defineOptions({
import { onMounted, ref } from 'vue'
import OrderRechangeSearch from '@/components/common/Search.vue'
import OrderRechangeTable from '@/components/common/Table.vue'
import { usePageLoading } from '@/composables/useLoading'
import OrderRechangePagination from '@/components/common/Pagination.vue'
import { getRechargeOrderListApi, reviewRechargeOrder } from '@/api/modules/order/rechange.ts'
import { search, tableColumns } from './options'
@ -86,6 +88,7 @@ const createDefaultSearchForm = (): SearchFormData => ({
const searchForm = ref<SearchFormData>(createDefaultSearchForm())
const { loading, startLoading, stopLoading } = usePageLoading()
//
const tableTree = ref<RechangeOrderItem[]>([])
const tableColumnsOptions = ref(tableColumns)
@ -109,6 +112,7 @@ const getRechargeStatusText = (status: string | number | null | undefined) => {
//
const getRechargeOrderList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
@ -150,6 +154,8 @@ const getRechargeOrderList = async () => {
tableTree.value = []
total.value = 0
console.error('获取充值订单列表失败', error)
} finally {
stopLoading()
}
}

View File

@ -16,6 +16,7 @@
:table-data="tableTree"
:columns="tableColumnsOptions"
row-key="id"
:loading="loading"
ref="tableRef"
>
</TransferTable>
@ -37,6 +38,7 @@ defineOptions({
//
import TransferSearch from '@/components/common/Search.vue'
import TransferTable from '@/components/common/Table.vue'
import { usePageLoading } from '@/composables/useLoading'
import TransferPagination from '@/components/common/Pagination.vue'
//
import { search, tableColumns } from './options'
@ -60,6 +62,7 @@ const searchForm = ref({
transferTime: [initTime.start, initTime.end],
})
const searchOptions = ref(search)
const { loading, startLoading, stopLoading } = usePageLoading()
/**
* @description: 定义表格数据
*/
@ -77,6 +80,7 @@ const total = ref(0)
*/
const getTransferDetailList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
@ -108,6 +112,8 @@ const getTransferDetailList = async () => {
}))
//
total.value = data.total
stopLoading()
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
}

View File

@ -5,7 +5,7 @@
@reset="handleReset"></CustomerListSearch>
<!-- 表格 -->
<CustomerListTable :table-data="tableTree" :columns="tableColumnsOptions" row-key="userId"
:default-sort="{ prop: 'createTime', order: 'descending' }" @expand-change="handleGetSubList">
:default-sort="{ prop: 'createTime', order: 'descending' }" :loading="loading" @expand-change="handleGetSubList">
<template #marginRatio="{ row }">
<el-button v-if="row.role_id === 5" type="primary" size="small" v-auth="'agent_getSelfVarietyPointDiffConfig'"
@click="handleMarginRatio(row)">
@ -112,6 +112,7 @@ defineOptions({
//
import CustomerListSearch from '@/components/common/Search.vue'
import CustomerListTable from '@/components/common/Table.vue'
import { usePageLoading } from '@/composables/useLoading'
import CustomerListPagination from '@/components/common/Pagination.vue'
import CustomerListDialog from '@/components/common/Dialog.vue'
import CustomerListForm from '@/components/common/Form.vue'
@ -145,6 +146,7 @@ const searchForm = ref({
const searchOptions = ref(search)
const tableColumnsOptions = ref(tableColumns)
const { loading, startLoading, stopLoading } = usePageLoading()
/**
* @description: 定义表格数据
*/
@ -291,6 +293,7 @@ const roleMap: any = {
*/
//
const getCustomerList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
@ -315,6 +318,8 @@ const getCustomerList = async () => {
//
total.value = data.total
stopLoading()
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
}

View File

@ -27,6 +27,7 @@
:table-data="marketTree"
:columns="marketTableColumnsOptions"
row-key="id"
:loading="loading"
@row-click="handleRowClick"
@row-contextmenu="handleRowContextMenu"
>
@ -195,6 +196,7 @@ defineOptions({
//
import MarketSearch from '@/components/common/Search.vue'
import MarketTable from '@/components/common/Table.vue'
import { usePageLoading } from '@/composables/useLoading'
import MarketPagination from '@/components/common/Pagination.vue'
import MarketDialog from '@/components/common/Dialog.vue'
import MarketForm from '@/components/common/Form.vue'
@ -239,6 +241,7 @@ const marketSearchForm = ref({
})
const marketSearchOptions = ref(marketSearch)
const { loading, startLoading, stopLoading } = usePageLoading()
/**
* @description 定义表格数据
*/
@ -565,6 +568,7 @@ const handleMarketFormLinkage = async (type: 'level' | 'parentAccountName', valu
*/
//
const getMarketList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
@ -573,8 +577,10 @@ const getMarketList = async () => {
const data = await getMarketListApi(params)
//
marketTree.value = mapMarketTree(data.data)
total.value = data.total
//
total.value = data.total
stopLoading()
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
}

View File

@ -15,7 +15,7 @@
</ClientSearch>
<!-- 表格组件 -->
<ClientTable :table-data="clientTree" :columns="clientTableColumns">
<ClientTable :table-data="clientTree" :columns="clientTableColumns" :loading="loading">
<template #status="{ row }">
{{ row.status === 1 ? '正常' : '禁用' }}
</template>
@ -137,6 +137,7 @@ defineOptions({
//
import ClientSearch from '@/components/common/Search.vue'
import ClientTable from '@/components/common/Table.vue'
import { usePageLoading } from '@/composables/useLoading'
import ClientPagination from '@/components/common/Pagination.vue'
import ClientDialog from '@/components/common/Dialog.vue'
import ClientForm from '@/components/common/Form.vue'
@ -172,6 +173,7 @@ const clientSearchForm = ref({
endDateTime: '',
})
const { loading, startLoading, stopLoading } = usePageLoading()
/**
* @description 定义表格数据
*/
@ -281,6 +283,7 @@ const mapObjectToOptions = (obj: Record<string, string>) => {
* @description 统一获取数据方法
*/
const getClientList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
@ -304,8 +307,9 @@ const getClientList = async () => {
//
agentUsername: item.par_uid === item.parent?.id ? item.parent?.username : '',
}))
//
total.value = Number(data.total)
//
stopLoading()
currentPage.value = Number(data.current_page)
pageSize.value = Number(data.per_page)
}

View File

@ -11,6 +11,7 @@
:columns="menuTableColumns"
row-key="id"
:tree-props="treeProps"
:loading="loading"
>
<template #icon="{ row }">
<el-icon v-if="row.icon && menuiconMap[row.icon]">
@ -71,6 +72,9 @@ defineOptions({
})
import type { FormInstance } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { usePageLoading } from '@/composables/useLoading'
const { loading, startLoading, stopLoading } = usePageLoading()
//
import MenuTable from '@/components/common/Table.vue'
import MenuDialog from '@/components/common/Dialog.vue'
@ -137,6 +141,7 @@ const handleAddMenu = () => {
//
const fetchMenuList = async () => {
startLoading()
try {
const data = await getMenuApi()
menuTree.value = data
@ -148,6 +153,8 @@ const fetchMenuList = async () => {
menuFormOptionsMap.value.parent_id = [{ label: '一级菜单', value: '0' }, ...parentNameOptions]
} catch (err) {
console.error('获取菜单列表失败', err)
} finally {
stopLoading()
}
}
//

View File

@ -14,7 +14,7 @@
</template>
</NoticeSearch>
<!-- 表格 -->
<NoticeTable :table-data="noticeTree" :columns="noticeTableColumnsOptions" row-key="id">
<NoticeTable :table-data="noticeTree" :columns="noticeTableColumnsOptions" row-key="id" :loading="loading">
<template #status="{ row }">
<!-- 修正状态显示1=草稿2=已发布 -->
{{ row.status === 1 ? '草稿' : '已发布' }}
@ -99,6 +99,9 @@
defineOptions({
name: 'Notice'
})
import { usePageLoading } from '@/composables/useLoading'
const { loading, startLoading, stopLoading } = usePageLoading()
//
import NoticeSearch from '@/components/common/Search.vue'
import NoticeTable from '@/components/common/Table.vue'
@ -223,6 +226,7 @@ const noticeFormOptionsMap = ref({
*/
//
const getNoticeList = async () => {
startLoading()
const params = {
page: currentPage.value,
page_size: pageSize.value,
@ -231,19 +235,23 @@ const getNoticeList = async () => {
publish_start_time: searchForm.value.startDateTime,
publish_end_time: searchForm.value.endDateTime,
}
const data: any = await getNoticeListApi(params)
//
noticeTree.value = data.data.map((item: any) => ({
id: item.id,
noticeName: item.name,
noticeContent: item.content,
publishTime: item.publish_time,
status: item.status,
}))
//
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
try {
const data: any = await getNoticeListApi(params)
//
noticeTree.value = data.data.map((item: any) => ({
id: item.id,
noticeName: item.name,
noticeContent: item.content,
publishTime: item.publish_time,
status: item.status,
}))
//
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
} finally {
stopLoading()
}
}
/**

View File

@ -6,7 +6,7 @@
<el-button type="primary" @click="handleAddRole" v-auth="'roles_create'">新增角色</el-button>
</div>
<!-- 角色列表表格 -->
<RoleTable :table-data="roleTree" :columns="roleTableColumns" row-key="id">
<RoleTable :table-data="roleTree" :columns="roleTableColumns" row-key="id" :loading="loading">
<template #status="{ row }">
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" active-text="启用"
inactive-text="禁用" />
@ -54,6 +54,8 @@ defineOptions({
})
import type { FormInstance, TreeInstance } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { usePageLoading } from '@/composables/useLoading'
const { loading, startLoading, stopLoading } = usePageLoading()
//
import RoleTable from '@/components/common/Table.vue'
@ -140,11 +142,14 @@ const filterRoles = (roleList: any[]) => {
//
const fetchRoleList = async () => {
startLoading()
try {
const data = await getRoleApi()
roleTree.value = data
} catch (err) {
console.error('获取角色列表失败', err)
} finally {
stopLoading()
}
}

View File

@ -3,7 +3,7 @@
<!-- 菜单列表头 -->
<MenuHeader :title="menuTitle" :buttons="menuHeaderButtons" @click="handleAddMenu" />
<!-- 菜单列表表格 -->
<MenuTable :table-data="menuTree" :columns="menuTableColumns" row-key="id">
<MenuTable :table-data="menuTree" :columns="menuTableColumns" row-key="id" :loading="loading">
<template #action="{ row }">
<el-button link type="primary" size="small" @click="handleEditMenu(row)"> 编辑 </el-button>
</template>
@ -33,6 +33,9 @@ defineOptions({
})
import type { FormInstance } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { usePageLoading } from '@/composables/useLoading'
const { loading, startLoading, stopLoading } = usePageLoading()
//
import MenuHeader from '@/components/common/Header.vue'
import MenuTable from '@/components/common/Table.vue'
@ -88,11 +91,14 @@ const handleAddMenu = () => {
//
const fetchSettingList = async () => {
startLoading()
try {
const data = await getSettingApi()
menuTree.value = data
} catch (err) {
console.error('获取菜单列表失败', err)
} finally {
stopLoading()
}
}
//

View File

@ -28,6 +28,7 @@
:columns="varietyTableColumnsOptions"
row-key="id"
@row-click="handleRowClick"
:loading="loading"
>
<template #onlineStatus="{ row }">
{{ ['', '上线', '下线'][row.onlineStatus] }}
@ -94,6 +95,9 @@ defineOptions({
name: 'Variety'
})
//
import { usePageLoading } from '@/composables/useLoading'
const { loading, startLoading, stopLoading } = usePageLoading()
import VarietySearch from '@/components/common/Search.vue'
import VarietyTable from '@/components/common/Table.vue'
import VarietyDialog from '@/components/common/Dialog.vue'
@ -233,31 +237,36 @@ const typeMap: any = {
//
const getVarietyList = async () => {
startLoading()
const params = {
name: searchForm.value.varietyName,
}
const data = await getVarietyListApi(params)
console.log('data', data)
//
varietyTree.value = data.map((item: any) => ({
...item,
id: item.id,
varietyName: item.name,
varietyCode: item.code,
onlineStatus: item.online_status,
tradeStatus: item.status,
minPoint: item.point_diff,
maxPoint: item.point_diff_max,
contractSize: item.multiplier,
minFlux: item.undulate_min,
unit: item.unit,
tradeGroup: item.group.name,
longStockFee: item.fee_inventory_long,
shortStockFee: item.fee_inventory_short,
profitLevel: item.stop_loss_level,
type: typeMap[item.type],
image: item.image,
}))
try {
const data = await getVarietyListApi(params)
console.log('data', data)
//
varietyTree.value = data.map((item: any) => ({
...item,
id: item.id,
varietyName: item.name,
varietyCode: item.code,
onlineStatus: item.online_status,
tradeStatus: item.status,
minPoint: item.point_diff,
maxPoint: item.point_diff_max,
contractSize: item.multiplier,
minFlux: item.undulate_min,
unit: item.unit,
tradeGroup: item.group.name,
longStockFee: item.fee_inventory_long,
shortStockFee: item.fee_inventory_short,
profitLevel: item.stop_loss_level,
type: typeMap[item.type],
image: item.image,
}))
} finally {
stopLoading()
}
}
//