This commit is contained in:
李远 2026-03-17 18:48:40 +08:00
parent 8d19a81d93
commit 59fd39341b
6 changed files with 322 additions and 20 deletions

View File

@ -0,0 +1,16 @@
import { request } from '@/api';
// 获取品种列表
export async function getVarietyListApi(params: any): Promise<any> {
return request.get<any>('/contractVariety/getList', {...params})
}
//创建合约品种
export async function createVarietyApi(params: any): Promise<any> {
return request.post<any>('/contractVariety/createVariety', {...params})
}
//编辑合约品种
export async function updateVarietyApi(params: any): Promise<any> {
return request.post<any>('/contractVariety/editVariety', {...params})
}

View File

@ -2,7 +2,7 @@
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-bind="$attrs">
<!-- 动态表单项 -->
<template v-for="(item, index) in formItems" :key="index">
<el-form-item :label="item.label" :prop="item.prop" :required="item.required" label-position="left" :label-width="item.labelWidth || '100px'">
<el-form-item :label="item.label" :prop="item.prop" :required="item.required" label-position="left" :label-width="item.labelWidth || '100px'" :class="item.class">
<!-- 输入框 -->
<el-input v-if="item.type === 'input'" v-model="formData[item.prop]" :placeholder="item.placeholder"
:disabled="item.disabled" clearable />
@ -42,6 +42,7 @@
{{ option.label }}
</el-checkbox>
</el-checkbox-group>
<el-switch v-else-if="item.type === 'switch'" v-model="formData[item.prop]" />
<!-- 自定义插槽 -->
<slot v-else :name="item.slotName" :formData="formData" />
</el-form-item>
@ -54,7 +55,7 @@ import type { FormInstance, FormRules } from 'element-plus'
import type { Component } from 'vue'
interface FormItem {
type: 'input' | 'select' | 'number' | 'radio' | 'slot' | 'checkbox'
type: 'input' | 'select' | 'number' | 'radio' | 'slot' | 'checkbox' | 'date' | 'switch'
label: string
prop: string
placeholder?: string
@ -65,6 +66,7 @@ interface FormItem {
slotName?: string //
labelPosition?: 'left' | 'right'
labelWidth?: string
class?: string
}
interface Props {

View File

@ -126,22 +126,7 @@ const agentFormOptionsMap = ref({
/**
* @description 定义弹窗表格数据
*/
const agentPointTree = ref([
{
id: '1001', //
varietyName: '欧元/美元', //
varietyCode: 'EURUSD', //
pointDifference: '50.00', //
assignedPointDifference: '' //
},
{
id: '1002',
varietyName: '英镑/美元',
varietyCode: 'GBPUSD',
pointDifference: '45.50',
assignedPointDifference: ''
}
])
const agentPointTree = ref([])
const agentPointTableColumnsOptions = computed(() => {
return dialogType.value !== 'view' ? agentPointTableColumns : viewAgentPointTableColumns;
});

View File

@ -1,3 +1,216 @@
<template>
<h1>品种</h1>
<div class="variety">
<!-- 搜索 -->
<VarietySearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch"
@reset="handleReset">
<template #button="{ form }">
<el-button type="primary" @click="handleEdit()">
编辑
</el-button>
<el-button type="primary" @click="handleAdd()">
添加
</el-button>
</template>
</VarietySearch>
<!-- 表格 -->
<VarietyTable :table-data="varietyTree" :columns="varietyTableColumnsOptions" row-key="id">
<template #onlineStatus="{ row }">
<el-switch :model-value="row.onlineStatus === 1" :active-value="true" :inactive-value="false" />
</template>
<template #tradeStatus="{ row }">
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" />
</template>
</VarietyTable>
<!-- 分页 -->
<VarietyPagination v-model="currentPage" v-model:pageSizeValue="pageSize" :total="total"
@pagination-change="handlePaginationChange" />
</div>
<!-- dialog -->
<VarietyDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" :fullscreen="dialogFullscreen" :width="dialogWidth"
@confirm="handleSubmit" @cancel="handleCancel" @close="handleClose">
<VarietyForm :form-data="varietyForm" :form-rules="varietyFormRules" :form-items="dialogFormItemOptions"
:options-map="varietyFormOptionsMap" ref="varietyFormRef" inline></VarietyForm>
</VarietyDialog>
<!-- dialog表格 -->
</template>
<script setup lang="ts">
//
import VarietySearch from '@/components/common/Search.vue'
import VarietyTable from '@/components/common/Table.vue'
import VarietyPagination from '@/components/common/Pagination.vue'
import VarietyDialog from '@/components/common/Dialog.vue'
import VarietyForm from '@/components/common/Form.vue'
//
import { search, tableColumns, editDialogFormItem } from './options'
import { rules } from './rules'
//
import { getVarietyListApi } from '@/api/modules/trade/variety'
//
/**
* @description: 定义搜索数据
*/
const searchForm = ref({
varietyName: '',
})
const searchOptions = ref(search)
/**
* @description: 定义表格数据
*/
const varietyTree = ref([])
const varietyTableColumnsOptions = ref(tableColumns)
/**
* @description: 定义分页数据
*/
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
/**
* @description: 定义弹窗数据
*/
const dialogWidth = ref('700px')
const dialogVisible = ref(false)
const dialogTitle = ref('')
const dialogType = ref('')
const dialogFullscreen = ref(false)
/**
* @description: 定义弹窗表格数据
*/
const varietyForm = ref({
varietyName: '',
varietyCode: '',
onlineStatus: 1,
status: 1,
currency: '',
minPoint: 0,
maxPoint: 0,
contractSize: 0,
minFlux: 0,
unit: '',
tradeGroup: '',
longStockFee: 0,
shortStockFee: 0,
profitLevel: 0,
})
const varietyFormRules = ref(rules)
const dialogFormItemOptions = computed(() => dialogType.value === 'edit' ? editDialogFormItem : [])
const varietyFormOptionsMap = ref({
currency: [],
tradeGroup: [],
})
/**
* @description: 定义公共数据处理方法
*/
/**
* @description: 定义公共请求数据方法
*/
//
const getVarietyList = async () => {
const params = {
page: currentPage.value,
page_size: pageSize.value,
user_name: searchForm.value.varietyName,
}
const data = await getVarietyListApi(params)
//
varietyTree.value = data.map((item: any) => ({
...item,
id: item.id,
varietyName: item.name,
varietyCode: item.code,
onlineStatus: item.online_status,
// tradeStatus: item.status,
currency: 'currency',
minPoint: item.point_diff,
maxPoint: item.point_diff_max,
contractSize: 'contractSize',
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
}))
//
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
}
/**
* @description: 页面加载完成需要请求的数据
*/
onMounted(() => {
getVarietyList()
})
/**
* @description: 定义搜索方法
*/
const handleSearch = async () => {
}
const handleReset = () => {
searchForm.value = {
varietyName: '',
}
handleSearch()
}
const handleAdd = () => {
dialogVisible.value = true
dialogTitle.value = '添加合约品种'
dialogType.value = 'add'
}
const handleEdit = () => {
dialogVisible.value = true
dialogTitle.value = '编辑合约品种'
dialogType.value = 'edit'
}
/**
* @description: 定义表格方法
*/
/**
* @description: 定义分页方法
*/
const handlePaginationChange = async (page: { currentPage: number, pageSize: number }) => {
currentPage.value = page.currentPage
pageSize.value = page.pageSize
await getVarietyList()
}
/**
* @description: 定义弹窗方法
*/
const handleSubmit = async () => {
dialogVisible.value = false
}
const handleCancel = () => {
dialogVisible.value = false
}
const handleClose = () => {
dialogVisible.value = false
}
/**
* @description: 定义弹窗表格方法
*/
</script>
<style scoped lang="scss">
.search-container {
:deep(.el-form) {
.el-form-item {
flex: none;
}
}
}
</style>

View File

@ -0,0 +1,78 @@
/**
* @description:
*/
export const search = [
// 品种名称
{ prop: 'varietyName', label: '品种名称', type: 'input' as const, placeholder: '请输入品种名称' },
]
/**
* @description:
*/
export const tableColumns = [
// id
{ prop: 'id', label: 'ID', align: 'center' as const },
// 名称
{ prop: 'varietyName', label: '名称', align: 'center' as const },
// 编号
{ prop: 'varietyCode', label: '编号', align: 'center' as const },
//上下线状态
{ slotName: 'onlineStatus', label: '上下线状态', align: 'center' as const },
// 交易状态
{ slotName: 'tradeStatus', label: '交易状态', align: 'center' as const },
// 币种
{ prop: 'currency', label: '币种', align: 'center' as const },
// 最小点差
{ prop: 'minPoint', label: '最小点差', align: 'center' as const },
// 最大点差
{ prop: 'maxPoint', label: '最大点差', align: 'center' as const },
// 合约大小
{ prop: 'contractSize', label: '合约大小', align: 'center' as const },
// 最小波动
{ prop: 'minFlux', label: '最小波动', align: 'center' as const },
// 单位
{ prop: 'unit', label: '单位', align: 'center' as const },
// 所属交易组
{ prop: 'tradeGroup', label: '所属交易组', align: 'center' as const },
// 多头库存费
{ prop: 'longStockFee', label: '多头库存费', align: 'center' as const },
// 空头库存费
{ prop: 'shortStockFee', label: '空头库存费', align: 'center' as const },
// 止盈水平
{ prop: 'profitLevel', label: '止盈水平', align: 'center' as const },
]
/**
* @description: dialog表单配置
*/
export const editDialogFormItem = [
// 名称
{ prop: 'varietyName', label: '名称', type: 'input' as const, placeholder: '请输入名称' },
// 编号
{ prop: 'varietyCode', label: '编号', type: 'input' as const, placeholder: '请输入编号' },
// 上下线状态
{ prop: 'onlineStatus', label: '上下线状态', type: 'switch' as const, class: 'online-status-switch' },
// 交易状态
{ prop: 'tradeStatus', label: '交易状态', type: 'switch' as const, class: 'trade-status-switch' },
// 币种
{ prop: 'currency', label: '币种', type: 'input' as const, placeholder: '请输入币种' },
// 最小点差
{ prop: 'minPoint', label: '最小点差', type: 'input' as const, placeholder: '请输入最小点差' },
// 最大点差
{ prop: 'maxPoint', label: '最大点差', type: 'input' as const, placeholder: '请输入最大点差' },
// 合约大小
{ prop: 'contractSize', label: '合约大小', type: 'input' as const, placeholder: '请输入合约大小' },
// 最小波动
{ prop: 'minFlux', label: '最小波动', type: 'input' as const, placeholder: '请输入最小波动' },
// 单位
{ prop: 'unit', label: '单位', type: 'input' as const, placeholder: '请输入单位' },
// 所属交易组
{ prop: 'tradeGroup', label: '所属交易组', type: 'input' as const, placeholder: '请输入所属交易组' },
// 多头库存费
{ prop: 'longStockFee', label: '多头库存费', type: 'input' as const, placeholder: '请输入多头库存费' },
// 空头库存费
{ prop: 'shortStockFee', label: '空头库存费', type: 'input' as const, placeholder: '请输入空头库存费' },
// 止盈水平
{ prop: 'profitLevel', label: '止盈水平', type: 'input' as const, placeholder: '请输入止盈水平' },
]

View File

@ -0,0 +1,8 @@
import type { FormRules } from 'element-plus'
export const rules = (): FormRules => {
return {
name: [
{ required: true, message: '请输入名称', trigger: ['blur'] }
],
}
}