This commit is contained in:
李远 2026-03-18 14:43:24 +08:00
parent 59fd39341b
commit bb9134f78d
11 changed files with 348 additions and 159 deletions

View File

@ -4,6 +4,10 @@ import { request } from '@/api';
export async function getVarietyListApi(params: any): Promise<any> { export async function getVarietyListApi(params: any): Promise<any> {
return request.get<any>('/contractVariety/getList', {...params}) return request.get<any>('/contractVariety/getList', {...params})
} }
//获取交易组列表
export async function getTradeGroupListApi(): Promise<any> {
return request.get<any>('/contractVariety/getGroupList')
}
//创建合约品种 //创建合约品种
export async function createVarietyApi(params: any): Promise<any> { export async function createVarietyApi(params: any): Promise<any> {
@ -11,6 +15,6 @@ export async function createVarietyApi(params: any): Promise<any> {
} }
//编辑合约品种 //编辑合约品种
export async function updateVarietyApi(params: any): Promise<any> { export async function editVarietyApi(params: any): Promise<any> {
return request.post<any>('/contractVariety/editVariety', {...params}) return request.post<any>('/contractVariety/editVariety', {...params})
} }

View File

@ -1,5 +1,6 @@
<template> <template>
<el-dialog :model-value="visible" :title="title" :width="width" :destroy-on-close="destroyOnClose" <el-dialog :model-value="visible" :title="title" :width="width" :destroy-on-close="destroyOnClose"
:fullscreen="fullscreen"
@close="handleClose" v-bind="$attrs"> @close="handleClose" v-bind="$attrs">
<!-- 对话框内容插槽 --> <!-- 对话框内容插槽 -->
<slot /> <slot />
@ -22,6 +23,7 @@ interface Props {
destroyOnClose?: boolean destroyOnClose?: boolean
type?: string type?: string
showFooter?: boolean showFooter?: boolean
fullscreen?: boolean
} }
interface Emits { interface Emits {
@ -32,9 +34,10 @@ interface Emits {
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
width: '600px', width: '750px',
destroyOnClose: true, destroyOnClose: true,
showFooter: true, showFooter: true,
fullscreen: false,
}) })
const emit = defineEmits<Emits>() const emit = defineEmits<Emits>()

View File

@ -1,52 +1,60 @@
<template> <template>
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-bind="$attrs"> <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-bind="$attrs">
<!-- 动态表单项 --> <!-- 动态表单项 -->
<template v-for="(item, index) in formItems" :key="index"> <el-row :gutter="props.rowGutter || 0">
<el-form-item :label="item.label" :prop="item.prop" :required="item.required" label-position="left" :label-width="item.labelWidth || '100px'" :class="item.class"> <template v-for="(item, index) in formItems" :key="index">
<!-- 输入框 --> <el-col :span="props.colSpan || 24">
<el-input v-if="item.type === 'input'" v-model="formData[item.prop]" :placeholder="item.placeholder" <el-form-item :label="item.label" :prop="item.prop" :required="item.required" label-position="left"
:disabled="item.disabled" clearable /> :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 />
<!-- 下拉选择框 --> <!-- 下拉选择框 -->
<el-select v-else-if="item.type === 'select'" v-model="formData[item.prop]" <el-select v-else-if="item.type === 'select'" v-model="formData[item.prop]"
:placeholder="item.placeholder" :disabled="item.disabled" clearable style="width: 100%" @change="handleItemChange(item.prop, formData[item.prop])"> :placeholder="item.placeholder" :disabled="item.disabled" clearable style="width: 100%"
<el-option v-for="option in props.optionsMap?.[item.prop] || []" :key="option.value" @change="handleItemChange(item.prop, formData[item.prop])">
:label="option.label" :value="option.value"> <el-option v-for="option in props.optionsMap?.[item.prop] || []" :key="option.value"
<template v-if="option.icon" #label> :label="option.label" :value="option.value">
<span style="display: flex; align-items: center; gap: 8px;"> <template v-if="option.icon" #label>
<el-icon v-if="option.icon"> <span style="display: flex; align-items: center; gap: 8px;">
<component :is="option.icon" /> <el-icon v-if="option.icon">
</el-icon> <component :is="option.icon" />
<span>{{ option.label }}</span> </el-icon>
</span> <span>{{ option.label }}</span>
</template> </span>
</el-option> </template>
</el-select> </el-option>
</el-select>
<!-- 数字输入框 --> <!-- 数字输入框 -->
<el-input-number v-else-if="item.type === 'number'" v-model="formData[item.prop]" :min="item.min" <el-input-number v-else-if="item.type === 'number'" v-model="formData[item.prop]"
:max="item.max" :placeholder="item.placeholder" :disabled="item.disabled" style="width: 100%" /> :min="item.min" :max="item.max" :placeholder="item.placeholder" :disabled="item.disabled"
style="width: 100%" />
<!-- 单选框组 --> <!-- 单选框组 -->
<el-radio-group v-else-if="item.type === 'radio'" v-model="formData[item.prop]"> <el-radio-group v-else-if="item.type === 'radio'" v-model="formData[item.prop]">
<el-radio v-for="option in props.optionsMap?.[item.prop] || []" :key="option.value" <el-radio v-for="option in props.optionsMap?.[item.prop] || []" :key="option.value"
:value="option.value"> :value="option.value">
{{ option.label }} {{ option.label }}
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
<!-- 复选框组 --> <!-- 复选框组 -->
<el-checkbox-group v-else-if="item.type === 'checkbox'" v-model="formData[item.prop]"> <el-checkbox-group v-else-if="item.type === 'checkbox'" v-model="formData[item.prop]">
<el-checkbox v-for="option in props.optionsMap?.[item.prop] || []" :key="option.value" <el-checkbox v-for="option in props.optionsMap?.[item.prop] || []" :key="option.value"
:value="option.value"> :value="option.value">
{{ option.label }} {{ option.label }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<el-switch v-else-if="item.type === 'switch'" v-model="formData[item.prop]" /> <el-switch v-else-if="item.type === 'switch'" v-model="formData[item.prop]" :active-value="1"
<!-- 自定义插槽 --> :inactive-value="2" />
<slot v-else :name="item.slotName" :formData="formData" /> <!-- 自定义插槽 -->
</el-form-item> <slot v-else :name="item.slotName" :formData="formData" />
</template> </el-form-item>
</el-col>
</template>
</el-row>
</el-form> </el-form>
</template> </template>
@ -67,6 +75,7 @@ interface FormItem {
labelPosition?: 'left' | 'right' labelPosition?: 'left' | 'right'
labelWidth?: string labelWidth?: string
class?: string class?: string
} }
interface Props { interface Props {
@ -78,6 +87,8 @@ interface Props {
value: string | number value: string | number
icon?: Component icon?: Component
}>> }>>
rowGutter?: number // 0
colSpan?: number // 24
} }
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
@ -85,7 +96,7 @@ const props = defineProps<Props>()
const emit = defineEmits(['form-item-change']) const emit = defineEmits(['form-item-change'])
const handleItemChange = (field: string, value: any) => { const handleItemChange = (field: string, value: any) => {
emit('form-item-change', field, value) emit('form-item-change', field, value)
} }
// //
defineExpose({ defineExpose({

View File

@ -24,24 +24,7 @@
:start-placeholder="item.startPlaceholder || '开始日期'" :start-placeholder="item.startPlaceholder || '开始日期'"
:end-placeholder="item.endPlaceholder || '结束日期'" :end-placeholder="item.endPlaceholder || '结束日期'"
:value-format="item.valueFormat || 'YYYY-MM-DD'" :clearable="item.clearable ?? true" :value-format="item.valueFormat || 'YYYY-MM-DD'" :clearable="item.clearable ?? true"
:disabled-date="item.disabledDate" :locale="'zhCn'" :disabled-date="item.disabledDate" :locale="'zhCn'" />
/>
<!-- 单选框组 -->
<el-radio-group v-else-if="item.type === 'radio'" v-model="searchForm[item.prop]"
:disabled="item.disabled">
<el-radio v-for="option in item.options" :key="option.value" :label="option.value">
{{ option.label }}
</el-radio>
</el-radio-group>
<!-- 复选框组 -->
<el-checkbox-group v-else-if="item.type === 'checkbox'" v-model="searchForm[item.prop]"
:disabled="item.disabled">
<el-checkbox v-for="option in item.options" :key="option.value" :label="option.value">
{{ option.label }}
</el-checkbox>
</el-checkbox-group>
</el-form-item> </el-form-item>
<!-- 自定义插槽项 --> <!-- 自定义插槽项 -->
@ -69,13 +52,11 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { Search } from '@element-plus/icons-vue'
// //
interface SearchOption { interface SearchOption {
prop: string; // prop: string; //
label: string; // label: string; //
type: 'input' | 'select' | 'date' | 'radio' | 'checkbox'; // type: 'input' | 'select' | 'date'; //
slot?: boolean; // slot?: boolean; //
placeholder?: string; // placeholder?: string; //
clearable?: boolean; // clearable?: boolean; //

View File

@ -62,6 +62,7 @@ const handleRowClick = (row: any) => {
<style scoped lang="scss"> <style scoped lang="scss">
.table-container { .table-container {
max-width: calc(100vw - 200px);
max-height: calc(100vh - 180px); max-height: calc(100vh - 180px);
overflow: auto; overflow: auto;
} }

View File

@ -368,4 +368,8 @@ const handleClose = () => {
} }
</script> </script>
<style scoped lang="scss"></style> <style scoped lang="scss">
.table-container{
max-width: 100%;
}
</style>

View File

@ -30,7 +30,7 @@
@cancel="handleCancel" @close="handleClose"> @cancel="handleCancel" @close="handleClose">
<ClientForm :form-data="clientForm" :form-rules="clientFormRules" :form-items="clientFormOptions" <ClientForm :form-data="clientForm" :form-rules="clientFormRules" :form-items="clientFormOptions"
:options-map="clientFormOptionsMap" ref="clientFormRef"> :options-map="clientFormOptionsMap" ref="clientFormRef">
<template #phoneOrEmail="{ formData }"> <template #phoneOrEmail="{ formData }" style="margin-left: 0;">
<div class="phone-email"> <div class="phone-email">
<div class="tab-btn"> <div class="tab-btn">
<el-button :type="activeTab === 'email' ? 'primary' : 'default'" size="small" <el-button :type="activeTab === 'email' ? 'primary' : 'default'" size="small"
@ -338,6 +338,10 @@ const handleClose = () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
:deep(.el-form-item__content) {
margin-left: 0 !important;
}
.phone-email { .phone-email {
display: flex; display: flex;
flex: 1; flex: 1;
@ -366,7 +370,7 @@ const handleClose = () => {
} }
.el-select { .el-select {
width: 110px; width: 120px;
} }
} }
} }

View File

@ -554,6 +554,9 @@ const handleClose = async () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
:deep(.el-form-item__content){
margin-left: 0 !important;
}
.market { .market {
.search-container { .search-container {
:deep(.el-form) { :deep(.el-form) {
@ -592,9 +595,12 @@ const handleClose = async () => {
} }
.el-select { .el-select {
width: 110px; width: 120px;
} }
} }
} }
} }
.table-container{
max-width: 100%;
}
</style> </style>

View File

@ -4,7 +4,7 @@
<VarietySearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch" <VarietySearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch"
@reset="handleReset"> @reset="handleReset">
<template #button="{ form }"> <template #button="{ form }">
<el-button type="primary" @click="handleEdit()"> <el-button type="primary" :disabled="!selectedRow" @click="handleEdit()">
编辑 编辑
</el-button> </el-button>
<el-button type="primary" @click="handleAdd()"> <el-button type="primary" @click="handleAdd()">
@ -12,25 +12,24 @@
</el-button> </el-button>
</template> </template>
</VarietySearch> </VarietySearch>
<!-- 表格 --> <!-- 表格 -->
<VarietyTable :table-data="varietyTree" :columns="varietyTableColumnsOptions" row-key="id"> <VarietyTable :table-data="varietyTree" :columns="varietyTableColumnsOptions" row-key="id"
@row-click="handleRowClick">
<template #onlineStatus="{ row }"> <template #onlineStatus="{ row }">
<el-switch :model-value="row.onlineStatus === 1" :active-value="true" :inactive-value="false" /> <el-switch :model-value="row.onlineStatus === 1" :active-value="true" :inactive-value="false" />
</template> </template>
<template #tradeStatus="{ row }"> <template #tradeStatus="{ row }">
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" /> <el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" />
</template> </template>
</VarietyTable> </VarietyTable>
<!-- 分页 -->
<VarietyPagination v-model="currentPage" v-model:pageSizeValue="pageSize" :total="total"
@pagination-change="handlePaginationChange" />
</div> </div>
<!-- dialog --> <!-- dialog -->
<VarietyDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" :fullscreen="dialogFullscreen" :width="dialogWidth" <VarietyDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @confirm="handleSubmit"
@confirm="handleSubmit" @cancel="handleCancel" @close="handleClose"> @cancel="handleCancel" @close="handleClose">
<VarietyForm :form-data="varietyForm" :form-rules="varietyFormRules" :form-items="dialogFormItemOptions" <VarietyForm :form-data="varietyForm" :form-rules="varietyFormRules" :form-items="dialogFormItemOptions"
:options-map="varietyFormOptionsMap" ref="varietyFormRef" inline></VarietyForm> :options-map="varietyFormOptionsMap" :row-gutter="rowGutter" :col-span="colSpan" ref="varietyFormRef">
</VarietyForm>
</VarietyDialog> </VarietyDialog>
<!-- dialog表格 --> <!-- dialog表格 -->
@ -40,17 +39,15 @@
// //
import VarietySearch from '@/components/common/Search.vue' import VarietySearch from '@/components/common/Search.vue'
import VarietyTable from '@/components/common/Table.vue' import VarietyTable from '@/components/common/Table.vue'
import VarietyPagination from '@/components/common/Pagination.vue'
import VarietyDialog from '@/components/common/Dialog.vue' import VarietyDialog from '@/components/common/Dialog.vue'
import VarietyForm from '@/components/common/Form.vue' import VarietyForm from '@/components/common/Form.vue'
// //
import { search, tableColumns, editDialogFormItem } from './options' import { search, tableColumns, editDialogFormItem } from './options'
import { rules } from './rules' import { rules } from './rules'
// //
import { getVarietyListApi } from '@/api/modules/trade/variety' import { getVarietyListApi, getTradeGroupListApi, editVarietyApi, createVarietyApi } from '@/api/modules/trade/variety'
//
/** /**
* @description: 定义搜索数据 * @description: 定义搜索数据
@ -66,99 +63,119 @@ const searchOptions = ref(search)
const varietyTree = ref([]) const varietyTree = ref([])
const varietyTableColumnsOptions = ref(tableColumns) const varietyTableColumnsOptions = ref(tableColumns)
/**
* @description: 定义分页数据
*/
const currentPage = ref(1)
const pageSize = ref(10)
const total = ref(0)
/** /**
* @description: 定义弹窗数据 * @description: 定义弹窗数据
*/ */
const dialogWidth = ref('700px')
const dialogVisible = ref(false) const dialogVisible = ref(false)
const dialogTitle = ref('') const dialogTitle = ref('')
const dialogType = ref('') const dialogType = ref('')
const dialogFullscreen = ref(false)
/** /**
* @description: 定义弹窗表数据 * @description: 定义弹窗表数据
*/ */
const varietyForm = ref({ const varietyForm = ref({
//
varietyName: '', varietyName: '',
//
varietyCode: '', varietyCode: '',
// 线
onlineStatus: 1, onlineStatus: 1,
status: 1, //
currency: '', tradeStatus: 1,
minPoint: 0, //
maxPoint: 0, minPoint: '',
contractSize: 0, //
minFlux: 0, maxPoint: '',
// ()
contractSize: '',
//
minFlux: '',
//
unit: '', unit: '',
//
tradeGroup: '', tradeGroup: '',
longStockFee: 0, //
shortStockFee: 0, longStockFee: '',
profitLevel: 0, //
shortStockFee: '',
//
profitLevel: '',
id: '',
groupId: '',
//
prepaymentHedge: '',
//
prepaymentPercent: '',
//
decimalPlaces: '',
//
pointDecimalPlaces: '',
}) })
const varietyFormRules = ref(rules) const varietyFormRef = ref<any>()
const dialogFormItemOptions = computed(() => dialogType.value === 'edit' ? editDialogFormItem : []) const varietyFormRules = ref(rules())
const dialogFormItemOptions = ref(editDialogFormItem)
const varietyFormOptionsMap = ref({ const varietyFormOptionsMap = ref({
currency: [],
tradeGroup: [], tradeGroup: [],
}) })
//
/** const selectedRow = ref<any>(null)
* @description: 定义公共数据处理方法 const rowGutter = ref(20)
*/ const colSpan = ref(12)
/** /**
* @description: 定义公共请求数据方法 * @description: 定义公共请求数据方法
*/ */
// //
const getVarietyList = async () => { const getVarietyList = async () => {
const params = { const params = {
page: currentPage.value, name: searchForm.value.varietyName,
page_size: pageSize.value,
user_name: searchForm.value.varietyName,
} }
const data = await getVarietyListApi(params) const data = await getVarietyListApi(params)
// console.log('data', data)
//
varietyTree.value = data.map((item: any) => ({ varietyTree.value = data.map((item: any) => ({
...item, ...item,
id: item.id, id: item.id,
varietyName: item.name, varietyName: item.name,
varietyCode: item.code, varietyCode: item.code,
onlineStatus: item.online_status, onlineStatus: item.online_status,
// tradeStatus: item.status, tradeStatus: item.status,
currency: 'currency',
minPoint: item.point_diff, minPoint: item.point_diff,
maxPoint: item.point_diff_max, maxPoint: item.point_diff_max,
contractSize: 'contractSize', contractSize: item.multiplier,
minFlux: item.undulate_min, minFlux: item.undulate_min,
unit: item.unit, unit: item.unit,
tradeGroup: item.group.name, tradeGroup: item.group.name,
longStockFee: item.fee_inventory_long, longStockFee: item.fee_inventory_long,
shortStockFee: item.fee_inventory_short, shortStockFee: item.fee_inventory_short,
profitLevel: item.stop_loss_level profitLevel: item.stop_loss_level,
})) }))
//
total.value = data.total
currentPage.value = data.current_page
pageSize.value = Number(data.per_page)
} }
//
const getTradeGroupList = async () => {
const data = await getTradeGroupListApi()
varietyFormOptionsMap.value.tradeGroup = data.map((item: any) => ({
label: item.name,
value: item.id,
}))
}
/** /**
* @description: 页面加载完成需要请求的数据 * @description: 页面加载完成需要请求的数据
*/ */
onMounted(() => { onMounted(() => {
getVarietyList() getVarietyList()
getTradeGroupList()
}) })
/** /**
* @description: 定义搜索方法 * @description: 定义搜索方法
*/ */
const handleSearch = async () => { const handleSearch = async () => {
getVarietyList()
} }
const handleReset = () => { const handleReset = () => {
searchForm.value = { searchForm.value = {
@ -166,31 +183,95 @@ const handleReset = () => {
} }
handleSearch() handleSearch()
} }
console.log('varietyForm.value)', varietyForm.value)
const handleEdit = () => {
getTradeGroupList()
const row = selectedRow.value;
varietyForm.value = {
...row,
id: row.id,
groupId: row.group.id,
//
prepaymentHedge: row.bail_hedge,
//
prepaymentPercent: row.bail_percent,
//
decimalPlaces: row.decimal_place,
//
pointDecimalPlaces: row.point_diff_decimal_place,
} as any
//
dialogVisible.value = true
dialogTitle.value = '编辑合约品种'
dialogType.value = 'edit'
}
const handleAdd = () => { const handleAdd = () => {
dialogVisible.value = true dialogVisible.value = true
dialogTitle.value = '添加合约品种' dialogTitle.value = '添加合约品种'
dialogType.value = 'add' dialogType.value = 'add'
} varietyForm.value = {
const handleEdit = () => { varietyName: '',
dialogVisible.value = true varietyCode: '',
dialogTitle.value = '编辑合约品种' onlineStatus: 1,
dialogType.value = 'edit' tradeStatus: 1,
minPoint: '',
maxPoint: '',
contractSize: '',
minFlux: '',
unit: '',
tradeGroup: '',
longStockFee: '',
shortStockFee: '',
profitLevel: '',
id: '',
groupId: '',
prepaymentHedge: '',
prepaymentPercent: '',
decimalPlaces: '',
pointDecimalPlaces: '',
}
} }
/** /**
* @description: 定义表格方法 * @description: 定义表格方法
*/ */
/**
* @description: 定义分页方法
*/
const handlePaginationChange = async (page: { currentPage: number, pageSize: number }) => {
currentPage.value = page.currentPage
pageSize.value = page.pageSize
await getVarietyList()
}
/** /**
* @description: 定义弹窗方法 * @description: 定义弹窗方法
*/ */
const handleSubmit = async () => { const handleSubmit = async () => {
await varietyFormRef.value?.validate()
const params = {
id: varietyForm.value.id,
code: varietyForm.value.varietyCode,
name: varietyForm.value.varietyName,
group_id: varietyForm.value.groupId,
point_diff: varietyForm.value.minPoint,
fee_inventory_short: varietyForm.value.shortStockFee,
status: varietyForm.value.tradeStatus,
bail_hedge: varietyForm.value.prepaymentHedge,
bail_percent: varietyForm.value.prepaymentPercent,
decimal_place: varietyForm.value.decimalPlaces,
stop_loss_level: varietyForm.value.profitLevel,
point_diff_max: varietyForm.value.maxPoint,
fee_inventory_long: varietyForm.value.longStockFee,
point_diff_decimal_place: varietyForm.value.pointDecimalPlaces,
unit: varietyForm.value.unit,
multiplier: varietyForm.value.contractSize,
undulate_min: varietyForm.value.minFlux,
online_status: varietyForm.value.onlineStatus,
}
if (dialogType.value === 'edit') {
console.log(params)
await editVarietyApi(params)
getVarietyList()
} else {
await createVarietyApi({...params, group_id: varietyForm.value.tradeGroup})
getVarietyList()
}
dialogVisible.value = false dialogVisible.value = false
} }
const handleCancel = () => { const handleCancel = () => {
@ -203,6 +284,14 @@ const handleClose = () => {
/** /**
* @description: 定义弹窗表格方法 * @description: 定义弹窗表格方法
*/ */
//
const handleRowClick = (row: any) => {
if (!row) {
selectedRow.value = null
return
}
selectedRow.value = row
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -20,8 +20,6 @@ export const tableColumns = [
{ slotName: 'onlineStatus', label: '上下线状态', align: 'center' as const }, { slotName: 'onlineStatus', label: '上下线状态', align: 'center' as const },
// 交易状态 // 交易状态
{ slotName: 'tradeStatus', 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: 'minPoint', label: '最小点差', align: 'center' as const },
// 最大点差 // 最大点差
@ -50,29 +48,35 @@ export const editDialogFormItem = [
{ prop: 'varietyName', label: '名称', type: 'input' as const, placeholder: '请输入名称' }, { prop: 'varietyName', label: '名称', type: 'input' as const, placeholder: '请输入名称' },
// 编号 // 编号
{ prop: 'varietyCode', 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: 'tradeGroup', label: '所属交易组', type: 'select' as const, placeholder: '请输入所属交易组' },
// 交易状态 // 最大点差
{ prop: 'tradeStatus', label: '交易状态', type: 'switch' as const, class: 'trade-status-switch' }, { prop: 'maxPoint', label: '最大点差', type: 'input' as const, placeholder: '请输入最大点差' },
// 币种
{ prop: 'currency', label: '币种', type: 'input' as const, placeholder: '请输入币种' },
// 最小点差 // 最小点差
{ prop: 'minPoint', 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: '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: 'longStockFee', label: '多头库存费', type: 'input' as const, placeholder: '请输入多头库存费' },
// 空头库存费 // 空头库存费
{ prop: 'shortStockFee', label: '空头库存费', type: 'input' as const, placeholder: '请输入空头库存费' }, { prop: 'shortStockFee', label: '空头库存费', type: 'input' as const, placeholder: '请输入空头库存费' },
// 预付款对冲
{ prop: 'prepaymentHedge', label: '预付款对冲', type: 'input' as const, placeholder: '请输入预付款对冲' },
// 预付款百分比
{ prop: 'prepaymentPercent', label: '预付款百分比', type: 'input' as const, placeholder: '请输入预付款百分比' },
// 小数位
{ prop: 'decimalPlaces', label: '小数位', type: 'input' as const, placeholder: '请输入小数位' },
// 点差小数位
{ prop: 'pointDecimalPlaces', label: '点差小数位', type: 'input' as const, placeholder: '请输入点差小数位' },
// 止盈水平 // 止盈水平
{ prop: 'profitLevel', label: '止盈水平', type: 'input' as const, placeholder: '请输入止盈水平' }, { prop: 'profitLevel', label: '止盈水平', type: 'input' as const, placeholder: '请输入止盈水平' },
// 单位
] { prop: 'unit', label: '单位', type: 'input' as const, placeholder: '请输入单位' },
// 最小波动
{ prop: 'minFlux', label: '最小波动', type: 'input' as const, placeholder: '请输入最小波动' },
// 上下线状态
{ prop: 'onlineStatus', label: '上下线状态', type: 'switch' as const},
// 交易状态
{ prop: 'tradeStatus', label: '交易状态', type: 'switch' as const},
]

View File

@ -1,8 +1,90 @@
import type { FormRules } from 'element-plus' import type { FormRules } from 'element-plus'
export const rules = (): FormRules => {
return { /**
name: [ *
{ required: true, message: '请输入名称', trigger: ['blur'] } * @param fieldName
], * @returns
*/
const validateMaxFiveDecimals = (fieldName: string) => {
return (rule: any, value: any, callback: any) => {
if (value !== undefined && value !== null && value !== '') {
const decimalPart = value.toString().split('.')[1]
if (decimalPart && decimalPart.length > 5) {
callback(new Error(`${fieldName}小数位不能超过5位`))
} else {
callback()
}
} else {
callback()
} }
}
}
export const rules = (): FormRules => {
return {
// 名称
varietyName: [
{ required: true, message: '请输入名称', trigger: ['blur'] }
],
// 编号
varietyCode: [
{ required: true, message: '请输入编号', trigger: ['blur'] }
],
// 所属交易组
tradeGroup: [
{ required: true, message: '请输入所属交易组', trigger: ['blur'] }
],
// 最大点差
maxPoint: [
{ required: true, message: '请输入最大点差', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('最大点差'), trigger: ['blur', 'change'] }
],
// 最小点差
minPoint: [
{ required: true, message: '请输入最小点差', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('最小点差'), trigger: ['blur', 'change'] }
],
// 合约大小
contractSize: [
{ required: true, message: '请输入合约大小', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('合约大小'), trigger: ['blur', 'change'] }
],
// 多头库存费
longStockFee: [
{ required: true, message: '请输入多头库存费', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('多头库存费'), trigger: ['blur', 'change'] }
],
// 空头库存费
shortStockFee: [
{ required: true, message: '请输入空头库存费', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('空头库存费'), trigger: ['blur', 'change'] }
],
// 预付款对冲
prepaymentHedge: [
{ required: true, message: '请输入预付款对冲', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('预付款对冲'), trigger: ['blur', 'change'] }
],
// 预付款百分比
prepaymentPercent: [
{ required: true, message: '请输入预付款百分比', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('预付款百分比'), trigger: ['blur', 'change'] }
],
// 小数位
decimalPlaces: [
{ required: true, message: '请输入小数位', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('小数位'), trigger: ['blur', 'change'] }
],
// 点差小数位
pointDecimalPlaces: [
{ required: true, message: '请输入点差小数位', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('点差小数位'), trigger: ['blur', 'change'] }
],
// 止盈水平
profitLevel: [
{ required: true, message: '请输入止盈水平', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('止盈水平'), trigger: ['blur', 'change'] }
]
}
} }