添加表头编辑
This commit is contained in:
parent
da0b61b8e2
commit
0ad61c0e69
|
|
@ -115,7 +115,7 @@ const handleBlur = () => {
|
|||
|
||||
<style scoped lang="scss">
|
||||
.search-container {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 4px;
|
||||
|
||||
.el-form {
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,57 @@
|
|||
<template>
|
||||
<div class="table-container">
|
||||
<div class="table-toolbar" v-if="showColumnSetting">
|
||||
<!-- 气泡确认框 -->
|
||||
<el-popover
|
||||
v-model:visible="columnSettingVisible"
|
||||
placement="bottom-end"
|
||||
:width="320"
|
||||
trigger="click"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button :icon="Setting" circle />
|
||||
</template>
|
||||
|
||||
<div class="column-setting-content">
|
||||
<!-- 操作栏 -->
|
||||
<div class="setting-header">
|
||||
<span class="setting-title">列设置</span>
|
||||
<el-button type="primary" size="small" text @click="handleReset">
|
||||
重置
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 拖拽列表 -->
|
||||
<div class="column-list">
|
||||
<draggable
|
||||
:list="localColumns"
|
||||
item-key="prop"
|
||||
handle=".drag-handle"
|
||||
:animation="200"
|
||||
ghost-class="ghost"
|
||||
@end="handleDragEnd"
|
||||
>
|
||||
<template #item="{ element }">
|
||||
<div class="column-item">
|
||||
<el-icon class="drag-handle"><Rank /></el-icon>
|
||||
<el-checkbox
|
||||
v-model="element.visible"
|
||||
:disabled="element.fixed"
|
||||
@change="handleVisibleChange"
|
||||
>
|
||||
{{ element.label }}
|
||||
</el-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
</draggable>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
<el-table
|
||||
ref="tableRef"
|
||||
style="width: 100%; flex: 1"
|
||||
:data="tableData"
|
||||
:data="enableClientFilter ? filteredTableData : tableData"
|
||||
:row-key="rowKey"
|
||||
:tree-props="treeProps"
|
||||
:border="border"
|
||||
|
|
@ -19,7 +67,7 @@
|
|||
<el-table-column v-if="showSelection" type="selection" width="55" align="center" />
|
||||
|
||||
<!-- 动态表头列 -->
|
||||
<template v-for="(column, index) in columns" :key="index">
|
||||
<template v-for="(column, index) in finalColumns" :key="index">
|
||||
<el-table-column
|
||||
v-if="column.type === 'index'"
|
||||
type="index"
|
||||
|
|
@ -28,17 +76,59 @@
|
|||
:align="column.align || 'center'"
|
||||
/>
|
||||
<el-table-column
|
||||
v-else-if="!column.slotName"
|
||||
v-else-if="!column.slotName && column.prop"
|
||||
:prop="column.prop"
|
||||
:label="column.label"
|
||||
:width="column.width"
|
||||
:align="column.align || 'left'"
|
||||
:sortable="column.sortable"
|
||||
:column-key="column.prop"
|
||||
>
|
||||
<template #header>
|
||||
<div class="table-header-cell">
|
||||
<div class="table-header-label">
|
||||
<span>{{ column.label }}</span>
|
||||
<template v-if="column.filters && column.filters.length > 0">
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
@command="(command: any) => handleFilterCommand(command, column)"
|
||||
>
|
||||
<span class="filter-trigger">
|
||||
<el-icon :class="{ 'is-active': filterStates[column.prop!]?.length }">
|
||||
<Filter />
|
||||
</el-icon>
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
v-for="item in column.filters"
|
||||
:key="item.value"
|
||||
:command="item.value"
|
||||
:divided="filterStates[column.prop!]?.includes(item.value)"
|
||||
>
|
||||
{{ item.text }}
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
</div>
|
||||
<el-input
|
||||
v-if="column.filterable"
|
||||
v-model="filterStates[column.prop!]"
|
||||
size="small"
|
||||
:placeholder="column.filterPlaceholder || '筛选'"
|
||||
clearable
|
||||
@change="handleFilterInput(column)"
|
||||
@clear="handleFilterClear(column)"
|
||||
class="header-filter-input"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<template v-if="column.isNumber" #default="{ row }">
|
||||
<span>{{ formatDecimalTruncate(row[column.prop]) }}</span>
|
||||
</template>
|
||||
<template v-else-if="column.options && column.prop" #default="{ row }">
|
||||
<template v-else-if="column.options" #default="{ row }">
|
||||
<span>{{ getOptionLabel(column.options, row[column.prop]) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -60,9 +150,16 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { ref, watch, computed, onMounted, reactive } from 'vue'
|
||||
import { Setting, Rank, Filter } from '@element-plus/icons-vue'
|
||||
import draggable from 'vuedraggable'
|
||||
import type { TableInstance } from 'element-plus'
|
||||
import { formatDecimalTruncate } from '@/utils/formatDecimal'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useUserStore } from '@/stores/modules/user'
|
||||
|
||||
// 筛选状态管理
|
||||
const filterStates = reactive<Record<string, any>>({})
|
||||
|
||||
// 根据选项配置获取标签
|
||||
const getOptionLabel = (options: { label: string; value: string | number }[], value: any): string => {
|
||||
|
|
@ -78,10 +175,18 @@ interface TableColumn {
|
|||
label: string
|
||||
width?: string | number
|
||||
align?: 'left' | 'center' | 'right'
|
||||
slotName?: string // 具名插槽名称
|
||||
sortable?: boolean // 是否可排序
|
||||
isNumber?: boolean // 是否为数字类型(自动截取小数位)
|
||||
options?: { label: string; value: string | number }[] // 选项配置(用于状态映射等)
|
||||
slotName?: string
|
||||
sortable?: boolean
|
||||
isNumber?: boolean
|
||||
options?: { label: string; value: string | number }[]
|
||||
visible?: boolean
|
||||
fixed?: boolean
|
||||
sortOrder?: number
|
||||
// 表头筛选器相关属性
|
||||
filters?: { text: string; value: any }[]
|
||||
filterMethod?: (value: any, row: any, column: any) => boolean
|
||||
filterable?: boolean
|
||||
filterPlaceholder?: string
|
||||
}
|
||||
|
||||
// 定义表格组件属性接口
|
||||
|
|
@ -92,10 +197,13 @@ interface Props {
|
|||
children: string
|
||||
}
|
||||
columns?: TableColumn[]
|
||||
border?: boolean // 是否显示边框
|
||||
highlightCurrentRow?: boolean // 是否高亮当前行
|
||||
loading?: boolean // 是否显示加载状态
|
||||
showSelection?: boolean // 是否显示勾选列
|
||||
border?: boolean
|
||||
highlightCurrentRow?: boolean
|
||||
loading?: boolean
|
||||
showSelection?: boolean
|
||||
showColumnSetting?: boolean
|
||||
columnSettingStorageKey?: string
|
||||
enableClientFilter?: boolean // 是否启用客户端筛选
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
|
|
@ -103,16 +211,170 @@ const props = withDefaults(defineProps<Props>(), {
|
|||
highlightCurrentRow: true,
|
||||
loading: false,
|
||||
showSelection: false,
|
||||
showColumnSetting: true, // 默认开启列设置
|
||||
columnSettingStorageKey: '',
|
||||
enableClientFilter: true, // 默认开启客户端筛选
|
||||
})
|
||||
|
||||
// 获取过滤后的数据
|
||||
const filteredTableData = computed(() => {
|
||||
if (!props.enableClientFilter || Object.keys(filterStates).length === 0) {
|
||||
return props.tableData
|
||||
}
|
||||
|
||||
return props.tableData.filter((row) => {
|
||||
for (const prop in filterStates) {
|
||||
const filterValue = filterStates[prop]
|
||||
if (Array.isArray(filterValue) && filterValue.length > 0) {
|
||||
if (!filterValue.includes(row[prop])) {
|
||||
return false
|
||||
}
|
||||
} else if (filterValue && typeof filterValue === 'string') {
|
||||
const cellValue = String(row[prop] || '').toLowerCase()
|
||||
if (!cellValue.includes(filterValue.toLowerCase())) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
// 定义组件抛出的事件
|
||||
const emit = defineEmits<{
|
||||
(e: 'row-click', row: any): void // 保留原有行点击事件
|
||||
(e: 'row-click', row: any): void
|
||||
(e: 'row-contextmenu', row: any, column: any, event: MouseEvent): void
|
||||
(e: 'selection-change', rows: any[]): void // 勾选变化事件
|
||||
(e: 'current-change', row: any): void // 当前行变化事件
|
||||
(e: 'selection-change', rows: any[]): void
|
||||
(e: 'current-change', row: any): void
|
||||
(e: 'filter-change', filters: { [key: string]: any }): void
|
||||
}>()
|
||||
|
||||
// 获取路由和用户 Store
|
||||
const route = useRoute()
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 生成缓存 key
|
||||
const getCacheKey = () => {
|
||||
const baseKey = props.columnSettingStorageKey || String(route.name || route.path)
|
||||
const userId = String(userStore.userInfo?.id || 'guest')
|
||||
return `table-column-setting-${baseKey}-${userId}`
|
||||
}
|
||||
|
||||
// 气泡确认框显示状态
|
||||
const columnSettingVisible = ref(false)
|
||||
|
||||
// 本地列配置副本
|
||||
const localColumns = ref<TableColumn[]>([])
|
||||
|
||||
// 计算最终使用的列配置
|
||||
const finalColumns = computed(() => {
|
||||
// 当 showColumnSetting 开启时,始终使用 localColumns
|
||||
if (props.showColumnSetting && localColumns.value.length > 0) {
|
||||
return localColumns.value.filter((col) => col.visible !== false)
|
||||
}
|
||||
return props.columns || []
|
||||
})
|
||||
|
||||
// 初始化列配置(从缓存或默认值)
|
||||
const initColumns = () => {
|
||||
if (!props.columns || props.columns.length === 0) {
|
||||
localColumns.value = []
|
||||
return
|
||||
}
|
||||
|
||||
const cacheKey = getCacheKey()
|
||||
const cached = localStorage.getItem(cacheKey)
|
||||
|
||||
if (cached) {
|
||||
try {
|
||||
const cachedConfig = JSON.parse(cached)
|
||||
// 按 sortOrder 排序
|
||||
cachedConfig.sort((a: any, b: any) => (a.sortOrder || 0) - (b.sortOrder || 0))
|
||||
|
||||
// 合并缓存和原始配置,保持缓存的顺序
|
||||
localColumns.value = cachedConfig.map((cached: any) => {
|
||||
const originalCol = props.columns?.find((c) => c.prop === cached.prop)
|
||||
if (originalCol) {
|
||||
return { ...originalCol, ...cached }
|
||||
}
|
||||
return null
|
||||
}).filter(Boolean)
|
||||
} catch {
|
||||
// 解析失败,使用默认配置
|
||||
localColumns.value = props.columns.map((col) => ({
|
||||
...col,
|
||||
visible: col.visible !== false,
|
||||
fixed: col.fixed || false,
|
||||
}))
|
||||
}
|
||||
} else {
|
||||
// 无缓存,使用默认配置
|
||||
localColumns.value = props.columns.map((col) => ({
|
||||
...col,
|
||||
visible: col.visible !== false,
|
||||
fixed: col.fixed || false,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
// 保存配置到 localStorage
|
||||
const saveToStorage = () => {
|
||||
const config = localColumns.value.map((col, index) => ({
|
||||
prop: col.prop,
|
||||
visible: col.visible,
|
||||
label: col.label,
|
||||
width: col.width,
|
||||
slotName: col.slotName,
|
||||
sortOrder: index,
|
||||
}))
|
||||
localStorage.setItem(getCacheKey(), JSON.stringify(config))
|
||||
}
|
||||
|
||||
// 处理可见性变化
|
||||
const handleVisibleChange = () => {
|
||||
saveToStorage()
|
||||
}
|
||||
|
||||
// 处理拖拽结束
|
||||
const handleDragEnd = () => {
|
||||
saveToStorage()
|
||||
}
|
||||
|
||||
// 重置为默认配置
|
||||
const handleReset = () => {
|
||||
localColumns.value = props.columns.map((col) => ({
|
||||
...col,
|
||||
visible: col.visible !== false,
|
||||
fixed: col.fixed || false,
|
||||
}))
|
||||
localStorage.removeItem(getCacheKey())
|
||||
columnSettingVisible.value = false
|
||||
}
|
||||
|
||||
// 监听 columns 变化
|
||||
watch(
|
||||
() => props.columns,
|
||||
(newColumns) => {
|
||||
if (newColumns && newColumns.length > 0) {
|
||||
// 只有在本地列为空时才初始化(不要覆盖已加载的缓存)
|
||||
if (localColumns.value.length === 0) {
|
||||
initColumns()
|
||||
}
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
// 组件挂载时初始化列配置
|
||||
onMounted(() => {
|
||||
// 延迟初始化,确保 props.columns 已准备好
|
||||
setTimeout(() => {
|
||||
if (props.columns && props.columns.length > 0 && localColumns.value.length === 0) {
|
||||
initColumns()
|
||||
}
|
||||
}, 100)
|
||||
})
|
||||
|
||||
// 处理勾选变化
|
||||
const handleSelectionChange = (rows: any[]) => {
|
||||
emit('selection-change', rows)
|
||||
|
|
@ -120,69 +382,72 @@ const handleSelectionChange = (rows: any[]) => {
|
|||
|
||||
// 处理当前行变化
|
||||
const handleCurrentChange = (row: any) => {
|
||||
// 添加空值保护,避免传递 null 导致 Vue 响应式系统报错
|
||||
if (row === null || row === undefined) {
|
||||
return
|
||||
}
|
||||
if (row === null || row === undefined) return
|
||||
emit('current-change', row)
|
||||
}
|
||||
|
||||
const tableRef = ref<TableInstance>()
|
||||
|
||||
// 维护当前选中行状态,用于二次点击取消选中
|
||||
// 维护当前选中行状态
|
||||
const selectedRow = ref<any>(null)
|
||||
|
||||
/**
|
||||
* 处理行点击事件(支持二次点击取消选中)
|
||||
*/
|
||||
// 处理行点击事件
|
||||
const handleRowClick = (row: any) => {
|
||||
// 增加空值保护,避免传递 null 给父组件
|
||||
if (!row) return
|
||||
|
||||
// 判断是否是二次点击同一行
|
||||
if (selectedRow.value && selectedRow.value === row) {
|
||||
// 二次点击:取消选中
|
||||
selectedRow.value = null
|
||||
tableRef.value?.setCurrentRow(null) // 传 null 清除选中
|
||||
tableRef.value?.setCurrentRow(null)
|
||||
} else {
|
||||
// 首次点击或点击不同行:选中该行
|
||||
selectedRow.value = row
|
||||
tableRef.value?.setCurrentRow(row)
|
||||
}
|
||||
|
||||
emit('row-click', selectedRow.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理行右键菜单事件
|
||||
*/
|
||||
// 处理行右键菜单事件
|
||||
const handleRowContextmenu = (row: any, column: any, event: MouseEvent) => {
|
||||
console.log('row', row)
|
||||
emit('row-contextmenu', row, column, event)
|
||||
}
|
||||
|
||||
// 监听 tableData 变化,数据更新时取消选中
|
||||
// 监听 tableData 变化
|
||||
watch(
|
||||
() => props.tableData,
|
||||
() => {
|
||||
// 数据更新时,清除选中状态
|
||||
selectedRow.value = null
|
||||
tableRef.value?.setCurrentRow(null)
|
||||
},
|
||||
{ deep: true }, // 深度监听,防止数组元素变化未触发
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
// 监听 loading 属性变化,确保状态同步
|
||||
watch(
|
||||
() => props.loading,
|
||||
(newVal) => {
|
||||
// loading 状态变化时可以执行额外的处理
|
||||
console.log('Table loading status changed:', newVal)
|
||||
},
|
||||
{ flush: 'sync' }, // 使用 sync 模式确保即时响应
|
||||
)
|
||||
// 处理下拉筛选命令
|
||||
const handleFilterCommand = (command: any, column: TableColumn) => {
|
||||
const prop = column.prop!
|
||||
if (!filterStates[prop]) {
|
||||
filterStates[prop] = []
|
||||
}
|
||||
|
||||
const index = filterStates[prop].indexOf(command)
|
||||
if (index > -1) {
|
||||
filterStates[prop].splice(index, 1)
|
||||
} else {
|
||||
filterStates[prop].push(command)
|
||||
}
|
||||
|
||||
emit('filter-change', { ...filterStates })
|
||||
}
|
||||
|
||||
// 暴露清除当前选中行的方法
|
||||
// 处理输入筛选
|
||||
const handleFilterInput = (column: TableColumn) => {
|
||||
emit('filter-change', { ...filterStates })
|
||||
}
|
||||
|
||||
// 处理清除筛选
|
||||
const handleFilterClear = (column: TableColumn) => {
|
||||
filterStates[column.prop!] = ''
|
||||
emit('filter-change', { ...filterStates })
|
||||
}
|
||||
|
||||
// 暴露方法
|
||||
defineExpose({
|
||||
clearCurrentRow: () => {
|
||||
selectedRow.value = null
|
||||
|
|
@ -203,9 +468,129 @@ defineExpose({
|
|||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
.table-toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 8px 0;
|
||||
|
||||
:deep(.el-button) {
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.column-setting-content {
|
||||
.setting-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
|
||||
.setting-title {
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
.column-list {
|
||||
max-height: 360px;
|
||||
overflow-y: auto;
|
||||
|
||||
.column-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 8px;
|
||||
margin-bottom: 4px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: #ebeef5;
|
||||
}
|
||||
|
||||
.drag-handle {
|
||||
margin-right: 10px;
|
||||
cursor: move;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
|
||||
&:hover {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-checkbox) {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.ghost {
|
||||
opacity: 0.5;
|
||||
background: #c6e2ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 表头单元格样式
|
||||
.table-header-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
width: 100%;
|
||||
|
||||
.table-header-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.filter-trigger {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
background: #f5f7fa;
|
||||
}
|
||||
|
||||
.el-icon {
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
|
||||
&.is-active {
|
||||
color: #409eff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header-filter-input {
|
||||
width: 100%;
|
||||
// max-width: 140px;
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
padding: 0 8px;
|
||||
font-size: 12px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
:deep(.el-input__inner) {
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
</header>
|
||||
<div class="table-container">
|
||||
<div class="table-container-left">
|
||||
<Table ref="singleTableRef" :table-data="tableData" :columns="tableColumns" row-key="id" :loading="loading"
|
||||
<Table ref="singleTableRef" :show-column-setting="false" :table-data="tableData" :columns="tableColumns" row-key="id" :loading="loading"
|
||||
:highlight-current-row="true" @current-change="handleCurrentChange" />
|
||||
</div>
|
||||
<div class="table-container-right">
|
||||
<Table row-key="id" :table-data="tableDataDetail" :columns="tableColumnsDetail" :loading="detailLoading" />
|
||||
<Table :show-column-setting="false" row-key="id" :table-data="tableDataDetail" :columns="tableColumnsDetail" :loading="detailLoading" />
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog v-model="dialogVisible" :title="dialogTitleType === 1 ? '添加手续费模板' : '编辑手续费模板'" width="500">
|
||||
|
|
|
|||
|
|
@ -8,26 +8,27 @@
|
|||
v-auth="'riskControl_editRiskControlSetting'">停用</el-button>
|
||||
<el-button type="primary" @click="handleChangeStatus(1)"
|
||||
v-auth="'riskControl_editRiskControlSetting'">启用</el-button>
|
||||
<el-button type="primary" :loading="syncLoading" @click="handleSyncRiskControl()" v-auth="'riskControl_editRiskControlSetting'">
|
||||
<el-button type="primary" :loading="syncLoading" @click="handleSyncRiskControl()"
|
||||
v-auth="'riskControl_editRiskControlSetting'">
|
||||
同步风控模板
|
||||
</el-button>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<div class="risk-table-content">
|
||||
<RiskTableSwitch :columns="tableColumnsSwitch" :table-data="tableTreeSwitch" class="table-switch"
|
||||
@row-click="handleRowClick" row-key="id" highlight-current-row :current-row-key="selectedRowId"
|
||||
:loading="loading">
|
||||
<RiskTableSwitch :columns="tableColumnsSwitch" :show-column-setting="false" :table-data="tableTreeSwitch"
|
||||
class="table-switch" @row-click="handleRowClick" row-key="id" highlight-current-row
|
||||
:current-row-key="selectedRowId" :loading="loading">
|
||||
<template #status="{ row }">
|
||||
<span>{{ row.status === 1 ? '启用' : '停用' }}</span>
|
||||
</template>
|
||||
</RiskTableSwitch>
|
||||
<RiskTableContent :columns="tableColumnsContent" :table-data="currentContent" class="table-content" row-key="id"
|
||||
:loading="detailLoading">
|
||||
<RiskTableContent :show-column-setting="false" :columns="tableColumnsContent" :table-data="currentContent"
|
||||
class="table-content" row-key="id" :loading="detailLoading">
|
||||
</RiskTableContent>
|
||||
</div>
|
||||
<!-- dialog -->
|
||||
<RiskDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" :button-loading="submitLoading" @confirm="handleSubmit"
|
||||
@cancel="handleCancel" @close="handleClose">
|
||||
<RiskDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" :button-loading="submitLoading"
|
||||
@confirm="handleSubmit" @cancel="handleCancel" @close="handleClose">
|
||||
<RiskForm :form-data="dialogForm" :form-rules="riskRules" :form-items="RiskFormItems"
|
||||
:options-map="riskFormOptionsMap" :row-gutter="rowGutter" :col-span="colSpan" ref="riskFormRef" />
|
||||
</RiskDialog>
|
||||
|
|
@ -194,7 +195,7 @@ const syncLoading = ref(false)
|
|||
const handleSyncRiskControl = async () => {
|
||||
syncLoading.value = true
|
||||
try {
|
||||
await syncRiskControlApi()
|
||||
await syncRiskControlApi()
|
||||
} finally {
|
||||
syncLoading.value = false
|
||||
}
|
||||
|
|
@ -251,7 +252,7 @@ const handleModifyRisk = () => {
|
|||
} as any
|
||||
}
|
||||
|
||||
const handleChangeStatus = async (status:any) => {
|
||||
const handleChangeStatus = async (status: any) => {
|
||||
dialogTitle.value = '停用'
|
||||
dialogType.value = 'status'
|
||||
await editRiskApi({ ...selectedRow.value, status: status })
|
||||
|
|
@ -272,7 +273,7 @@ const handleRowClick = (row: any) => {
|
|||
}
|
||||
selectedRowId.value = row.id
|
||||
// 找到对应的数据并更新右侧内容
|
||||
const targetItem:any = tableTreeContent.value.find((item: any) => item.id === row.id)
|
||||
const targetItem: any = tableTreeContent.value.find((item: any) => item.id === row.id)
|
||||
|
||||
const fields = [
|
||||
{ text: '单笔开仓最大数量' + targetItem.maxOpenPosition },
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
:table-data="marketTree"
|
||||
:columns="marketTableColumnsOptions"
|
||||
row-key="id"
|
||||
:show-column-setting="true"
|
||||
:loading="loading"
|
||||
@row-click="handleRowClick"
|
||||
@row-contextmenu="handleRowContextMenu"
|
||||
|
|
@ -35,7 +36,7 @@
|
|||
<template #floatProfitLoss="{ row }">
|
||||
<span>{{ getMarketFloatProfit(row.id) }}</span>
|
||||
</template>
|
||||
<template #closeProfitLoss="{ row }">
|
||||
<template #s="{ row }">
|
||||
<span>{{ getMarketCloseProfit(row.id) }}</span>
|
||||
</template>
|
||||
<template #pointSpread="{ row }">
|
||||
|
|
|
|||
|
|
@ -12,15 +12,15 @@ export const marketSearch = [
|
|||
|
||||
export const marketTableColumns = [
|
||||
// id
|
||||
{ label: 'ID', prop: 'id', align: 'center' as const, width: '100px' },
|
||||
{ label: 'ID', prop: 'id', align: 'center' as const, width: '100px',filterable:false },
|
||||
//代理关系
|
||||
{ label: '代理关系', prop: 'agentRelation', align: 'center' as const, width: '200px' },
|
||||
{ label: '代理关系', prop: 'agentRelation', align: 'center' as const, width: '290' },
|
||||
//账户名
|
||||
{ label: '账户名', prop: 'accountName', align: 'center' as const, width: '120px' },
|
||||
//级别
|
||||
{ label: '级别', prop: 'level', align: 'center' as const, width: '120px' },
|
||||
{ label: '邮箱', prop: 'email', align: 'center' as const, width: '160px' },
|
||||
{ label: '手机号', prop: 'mobile', align: 'center' as const, width: '140px' },
|
||||
{ label: '手机号', prop: 'mobile', align: 'center' as const, width: '180' },
|
||||
{ label: '风险率', prop: 'ratio', align: 'center' as const, width: '120px' },
|
||||
//基本账户
|
||||
{ label: '基本账户', prop: 'basicAccount', align: 'center' as const, isNumber: true , width: '200px' },
|
||||
|
|
|
|||
Loading…
Reference in New Issue