feat: 重命名交易对管理为代币化交易对管理,并新增交易对的添加和编辑功能

This commit is contained in:
2026-01-07 17:16:57 +07:00
parent c9c2288c2a
commit 7fd004e4d2
9 changed files with 15 additions and 17 deletions

View File

@@ -0,0 +1,178 @@
<script lang="ts" setup>
import { computed, ref, useTemplateRef } from 'vue';
import type { FormInst, FormRules } from 'naive-ui';
import { client, safeClient } from '@/service/api';
type Body = CommonType.TreatyBody<typeof client.api.admin.trading_pairs.post>;
defineOptions({
name: 'TradingPairAdd'
});
const emit = defineEmits<{
(e: 'close'): void;
}>();
const formInst = useTemplateRef<FormInst>('formInst');
const form = ref<Body>({
symbol: '',
name: '',
baseAsset: '',
quoteAsset: 'USDT',
description: '',
minOrderAmount: '0',
minOrderQuantity: '0',
makerFeeRate: '0',
takerFeeRate: '0',
iconUrl: '',
isActive: true,
marginEnabled: false,
maxLeverage: null,
spotEnabled: true
});
// 用于表单输入的临时数字值
const tempValues = ref({
minOrderAmount: 0,
minOrderQuantity: 0,
makerFeeRate: 0,
takerFeeRate: 0,
maxLeverage: 1
});
const rules: FormRules = {
symbol: [{ required: true, message: '请输入交易对标识', trigger: ['blur', 'input'] }],
name: [{ required: true, message: '请输入交易对显示名称', trigger: ['blur', 'input'] }],
baseAsset: [{ required: true, message: '请输入基础资产代码', trigger: ['blur', 'input'] }],
quoteAsset: [{ required: true, message: '请输入计价资产代码', trigger: ['blur', 'input'] }],
minOrderAmount: [{ required: true, message: '请输入最小下单金额', trigger: ['blur', 'change'] }],
minOrderQuantity: [{ required: true, message: '请输入最小下单数量', trigger: ['blur', 'change'] }],
makerFeeRate: [{ required: true, message: '请输入挂单手续费率', trigger: ['blur', 'change'] }],
takerFeeRate: [{ required: true, message: '请输入成交手续费率', trigger: ['blur', 'change'] }]
};
const showMaxLeverage = computed(() => form.value.marginEnabled);
const { data: assets } = safeClient(client.api.admin.assets.get());
const assetsOption = computed(() => {
return assets.value?.data
.filter(item => item.code !== 'USDT')
.map(item => ({
label: item.code,
value: item.code
}));
});
// 同步数字输入到表单字符串
function syncNumberToString() {
form.value.minOrderAmount = tempValues.value.minOrderAmount.toString();
form.value.minOrderQuantity = tempValues.value.minOrderQuantity.toString();
form.value.makerFeeRate = (tempValues.value.makerFeeRate / 100).toString();
form.value.takerFeeRate = (tempValues.value.takerFeeRate / 100).toString();
if (form.value.marginEnabled) {
form.value.maxLeverage = tempValues.value.maxLeverage;
} else {
form.value.maxLeverage = null;
}
}
function handleSubmit() {
formInst.value?.validate(async errors => {
if (!errors) {
syncNumberToString();
await safeClient(() => client.api.admin.trading_pairs.post(form.value));
emit('close');
}
});
}
</script>
<template>
<div class="my-10">
<NForm
ref="formInst"
:model="form"
label-width="140px"
label-placement="left"
:rules="rules"
require-mark-placement="left"
>
<NFormItem path="name" label="交易对显示名称">
<NInput v-model:value="form.name" placeholder="如:比特币/泰达币" />
</NFormItem>
<NFormItem path="iconUrl" label="交易对图标">
<IconPicker v-model="form.iconUrl" :collections="['cryptocurrency-color']" />
</NFormItem>
<NGrid :cols="2" :x-gap="12">
<NFormItemGi path="baseAsset" label="基础资产代码">
<NSelect
:value="form.baseAsset || undefined"
:options="assetsOption"
placeholder="如BTC"
@update:value="val => (form.baseAsset = val)"
/>
</NFormItemGi>
<NFormItemGi path="quoteAsset" label="计价资产代码">
<NInput v-model:value="form.quoteAsset" placeholder="如USDT" readonly disabled />
</NFormItemGi>
</NGrid>
<NGrid :cols="2" :x-gap="12">
<NFormItemGi path="minOrderAmount" label="最小下单金额USDT">
<NInputNumber v-model:value="tempValues.minOrderAmount" :min="0" :precision="2" class="w-full" />
</NFormItemGi>
<NFormItemGi path="minOrderQuantity" label="最小下单数量">
<NInputNumber v-model:value="tempValues.minOrderQuantity" :min="0" :precision="8" class="w-full" />
</NFormItemGi>
</NGrid>
<NGrid :cols="2" :x-gap="12">
<NFormItemGi path="makerFeeRate" label="挂单手续费率">
<NInputNumber v-model:value="tempValues.makerFeeRate" :min="0" :max="100" :step="0.01" class="w-full">
<template #suffix>%</template>
</NInputNumber>
</NFormItemGi>
<NFormItemGi path="takerFeeRate" label="成交手续费率">
<NInputNumber v-model:value="tempValues.takerFeeRate" :min="0" :max="100" :step="0.01" class="w-full">
<template #suffix>%</template>
</NInputNumber>
</NFormItemGi>
</NGrid>
<NFormItem path="description" label="交易对描述">
<NInput v-model:value="form.description" type="textarea" placeholder="请输入交易对描述" />
</NFormItem>
<NGrid :cols="2" :x-gap="12">
<NFormItemGi path="spotEnabled" label="是否支持现货交易">
<NSwitch v-model:value="form.spotEnabled" />
</NFormItemGi>
<NFormItemGi path="isActive" label="是否启用">
<NSwitch v-model:value="form.isActive" />
</NFormItemGi>
<NFormItemGi path="marginEnabled" label="是否支持杠杆交易">
<NSwitch v-model:value="form.marginEnabled" />
</NFormItemGi>
<NFormItemGi v-if="showMaxLeverage" path="maxLeverage" label="最大杠杆倍数">
<NInputNumber v-model:value="tempValues.maxLeverage" :min="1" :max="100" :precision="0" class="w-full">
<template #suffix></template>
</NInputNumber>
</NFormItemGi>
</NGrid>
<NSpace justify="end">
<NButton type="primary" ghost @click="$emit('close')"> </NButton>
<NButton type="primary" @click="handleSubmit"> </NButton>
</NSpace>
</NForm>
</div>
</template>
<style lang="css" scoped></style>