BUG修复及dashboard页面接口对接

This commit is contained in:
Songsl 2026-04-26 21:05:03 +08:00
parent 44e43d81f3
commit 12dd2268ac
5 changed files with 890 additions and 783 deletions

View File

@ -0,0 +1,12 @@
import { request } from '@/api'
// 获取账户列表
export async function getAllAccount(params: any): Promise<any> {
return await request.get<any>('/user/getAllAccount', params)
}
// 获取用户钱包资金
export async function getWalletCapital(): Promise<any> {
return await request.get<any>('/user/getWalletCapital')
}

View File

@ -61,11 +61,20 @@
<div class="wallet">
<div class="item">
<el-icon color="#409eff" size="40">
<svg t="1773987067376" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="1663" width="200" height="200">
<svg
t="1773987067376"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="1663"
width="200"
height="200"
>
<path
d="M512 97.52381c228.912762 0 414.47619 185.563429 414.47619 414.47619s-185.563429 414.47619-414.47619 414.47619S97.52381 740.912762 97.52381 512 283.087238 97.52381 512 97.52381z m96.060952 193.584761L512 387.120762l-96.060952-96.060952-51.687619 51.73638 96.036571 96.012191L329.142857 438.857143v73.142857h146.285714v60.952381h-146.285714v73.142857h146.285714v97.52381h73.142858v-97.52381h146.285714v-73.142857h-146.285714V512h146.285714v-73.142857h-131.145143l96.060952-96.060953-51.736381-51.687619z"
p-id="1664"></path>
p-id="1664"
></path>
</svg>
</el-icon>
</div>
@ -77,21 +86,21 @@
</div>
<div class="item">
<span>主钱包</span>
<span>1000000</span>
<span>1000000</span>
<span>1000000</span>
<span>{{ walletCapital.amount_total }}</span>
<span>{{ walletCapital.amount }}</span>
<span>{{ walletCapital.freeze }}</span>
</div>
</div>
</template>
</el-popover>
</el-card>
<el-card class="account">
<h3 class="account-title">
个人账户
<el-button type="primary" size="small" @click="handleAddSubAccount">添加子账户</el-button>
</h3>
<div class="list">
<div class="account-list">
<div class="list" v-for="item in accountList" :key="item.id">
<div class="item item-setting">
<div class="setting-content" v-if="!isEdit">
<span>账户名称:</span>
@ -100,8 +109,14 @@
<div class="setting-content" v-else>
<span class="setting-label">账户名称:</span>
<span v-if="!isEdit">{{ accountName }}</span>
<el-input v-model="editName" @blur="handleSave" @keyup.enter="handleSave" ref="inputRef"
size="small" v-else />
<el-input
v-model="editName"
@blur="handleSave"
@keyup.enter="handleSave"
ref="inputRef"
size="small"
v-else
/>
</div>
<div class="setting-group">
<span>
@ -118,19 +133,20 @@
</div>
<div class="item">
<span>账户号</span>
<span>12345678901234567890</span>
<span>{{ item.account_id || '--' }}</span>
</div>
<div class="item">
<span>净资产</span>
<span>1000000</span>
<span>{{ item?.wallets_trade?.amount || '--' }}</span>
</div>
<div class="item">
<span>余额</span>
<span>1000000</span>
<span>{{ item?.wallets_trade?.amount || '--' }}</span>
</div>
<div class="item">
<span>杠杆</span>
<span>1:5000</span>
<span>1:{{ item?.wallets_trade?.lever || '--' }}</span>
</div>
</div>
</div>
</el-card>
@ -152,7 +168,7 @@
<div class="item">
<span>推广二维码</span>
<div class="text">
<img :src="qrCode" alt="推广二维码">
<img :src="qrCode" alt="推广二维码" />
<el-icon @click="handleCopyQrCode">
<DocumentCopy />
</el-icon>
@ -161,17 +177,35 @@
</div>
</el-card>
</div>
<AgentDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @confirm="handleSubmit"
@cancel="handleCancel" @close="handleClose">
<AgentDialog
:visible="dialogVisible"
:title="dialogTitle"
:type="dialogType"
@confirm="handleSubmit"
@cancel="handleCancel"
@close="handleClose"
>
<div class="tab" v-if="dialogType !== 'add'">
<el-button :type="dialogType === 'setting' ? 'primary' : 'default'"
@click="dialogType = 'setting'">重置密码</el-button>
<el-button :type="dialogType === 'leverage' ? 'primary' : 'default'"
@click="dialogType = 'leverage'">修改杠杆</el-button>
<el-button
:type="dialogType === 'setting' ? 'primary' : 'default'"
@click="dialogType = 'setting'"
>重置密码</el-button
>
<el-button
:type="dialogType === 'leverage' ? 'primary' : 'default'"
@click="dialogType = 'leverage'"
>修改杠杆</el-button
>
</div>
<AgentForm :form-data="subAccountForm" :form-rules="subAccountRules" :form-items="subAccountFormItem"
:options-map="subAccountFormOptionsMap" :row-gutter="rowGutter" :col-span="colSpan"
ref="subAccountFormRef" />
<AgentForm
:form-data="subAccountForm"
:form-rules="subAccountRules"
:form-items="subAccountFormItem"
:options-map="subAccountFormOptionsMap"
:row-gutter="rowGutter"
:col-span="colSpan"
ref="subAccountFormRef"
/>
</AgentDialog>
</template>
@ -188,10 +222,20 @@ import { formItem, resetPasswordFormItem, leverageFormItem } from './options'
import { rules } from './rules'
//
import { getLeverOptionsApi, createAgentApi, editAgentNameApi, resetPasswordApi, leverageLeverApi } from '@/api/modules/agent'
import {
getLeverOptionsApi,
createAgentApi,
editAgentNameApi,
resetPasswordApi,
leverageLeverApi,
} from '@/api/modules/agent'
import { getAllAccount, getWalletCapital } from '@/api/modules/dashboard.ts'
//
import { getStorage, setStorage } from '@/utils/storage'
import { useUserStore } from '@/stores/modules/user.ts'
const userStore = useUserStore()
/**
* @description: dialog数据
@ -200,6 +244,20 @@ const dialogVisible = ref(false)
const dialogTitle = ref('')
const dialogType = ref('add')
const accountList = ref([])
const getAccoundList = async () => {
const res = await getAllAccount({ username: userStore.userInfo.username })
console.log(res)
accountList.value = res
}
const walletCapital = ref({})
const getWalletCapitaInfo = async () => {
const res = await getWalletCapital()
console.log('getWalletCapitaInfo', res)
walletCapital.value = res
}
/**
* @description: 添加子账户表单数据
*/
@ -209,7 +267,7 @@ const subAccountForm = ref({
//
resetPassword: '',
//
confirmPassword: ''
confirmPassword: '',
})
const subAccountFormRef = ref()
const subAccountRules = ref(rules(subAccountForm.value))
@ -253,7 +311,7 @@ const getLeverOptions = async () => {
console.log(data)
subAccountFormOptionsMap.value.leverage = data.map((item: any) => ({
label: item.label,
value: item.value
value: item.value,
}))
} catch (err) {
console.error('获取杠杆选项失败:', err)
@ -265,6 +323,8 @@ const getLeverOptions = async () => {
*/
onMounted(() => {
getLeverOptions()
getAccoundList()
getWalletCapitaInfo()
})
/**
@ -285,26 +345,26 @@ const handleSubmit = async () => {
await subAccountFormRef.value.validate()
const params = {
password: subAccountForm.value.password,
lever: subAccountForm.value.leverage
lever: subAccountForm.value.leverage,
}
if (dialogType.value === 'add') {
await createAgentApi(params)
dialogVisible.value = false
} else if (dialogType.value === 'setting') {
const params = {
reg_type:userInfo?.reg_type || '',
reg_type: userInfo?.reg_type || '',
login_password1: subAccountForm.value.resetPassword,
login_password2: subAccountForm.value.confirmPassword,
email: userInfo?.email || '',
mobile: userInfo?.mobile || '',
code: '123456'
code: '123456',
}
await resetPasswordApi(params)
dialogVisible.value = false
} else if (dialogType.value === 'leverage') {
const params = {
account_id: userInfo?.id || '',
lever: subAccountForm.value.leverage
lever: subAccountForm.value.leverage,
}
await leverageLeverApi(params)
dialogVisible.value = false
@ -334,12 +394,12 @@ const handleSave = async () => {
if (editName.value.trim()) {
await editAgentNameApi({
account_id: userInfo?.id || '',
account_name: accountName.value
account_name: accountName.value,
})
accountName.value = editName.value.trim()
setStorage('userInfo', {
...userInfo,
username: accountName.value
username: accountName.value,
})
} else {
editName.value = accountName.value //
@ -377,8 +437,8 @@ const handleCopyQrCode = async () => {
// 2. png/jpeg
await navigator.clipboard.write([
new ClipboardItem({
[blob.type]: blob
})
[blob.type]: blob,
}),
])
ElMessage.success('图片复制成功!')
} catch (err) {
@ -386,7 +446,6 @@ const handleCopyQrCode = async () => {
ElMessage.error('图片复制失败,请检查图片格式或权限')
}
}
</script>
<style scoped lang="scss">
@ -496,6 +555,14 @@ const handleCopyQrCode = async () => {
gap: 10px;
}
.account-list {
display: flex;
flex-wrap: wrap;
align-items: center;
column-gap: 12px;
row-gap: 12px;
}
.account {
.list {
width: 300px;

View File

@ -1,23 +1,31 @@
<template>
<div class="variety">
<!-- 搜索 -->
<VarietySearch :search-form="searchForm" :search-options="searchOptions" @search="handleSearch"
@reset="handleReset">
<VarietySearch
:search-form="searchForm"
:search-options="searchOptions"
@search="handleSearch"
@reset="handleReset"
>
<template #button="{ form }">
<el-button type="primary" :disabled="!selectedRow" @click="handleEdit()">
编辑
</el-button>
<el-button type="primary" @click="handleAdd()">
添加
</el-button>
<el-button type="primary" :disabled="!selectedRow" @click="handleEdit()"> 编辑 </el-button>
<el-button type="primary" @click="handleAdd()"> 添加 </el-button>
</template>
</VarietySearch>
<!-- 表格 -->
<VarietyTable :table-data="varietyTree" :columns="varietyTableColumnsOptions" row-key="id"
@row-click="handleRowClick">
<VarietyTable
:table-data="varietyTree"
:columns="varietyTableColumnsOptions"
row-key="id"
@row-click="handleRowClick"
>
<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 #tradeStatus="{ row }">
<el-switch :model-value="row.status === 1" :active-value="true" :inactive-value="false" />
@ -25,33 +33,52 @@
</VarietyTable>
</div>
<!-- dialog -->
<VarietyDialog :visible="dialogVisible" :title="dialogTitle" :type="dialogType" @confirm="handleSubmit"
@cancel="handleCancel" @close="handleClose">
<VarietyForm :form-data="varietyForm" :form-rules="varietyFormRules" :form-items="dialogFormItemOptions"
:options-map="varietyFormOptionsMap" :row-gutter="rowGutter" :col-span="colSpan" ref="varietyFormRef">
<VarietyDialog
:visible="dialogVisible"
:title="dialogTitle"
:type="dialogType"
@confirm="handleSubmit"
@cancel="handleCancel"
@close="handleClose"
>
<VarietyForm
:form-data="varietyForm"
:form-rules="varietyFormRules"
:form-items="dialogFormItemOptions"
:options-map="varietyFormOptionsMap"
:row-gutter="rowGutter"
:col-span="colSpan"
ref="varietyFormRef"
>
<template #upload="{ formData }">
<el-upload v-model:file-list="fileList" class="upload-demo" :http-request="handleUpload"
:before-upload="beforeUpload" :limit="1">
<el-upload
v-model:file-list="fileList"
class="upload-demo"
:http-request="handleUpload"
:before-upload="beforeUpload"
:limit="1"
>
<el-button type="primary">点击上传</el-button>
<template #tip>
<div class="el-upload__tip">
jpg/png格式 图片大小不能超过20KB
</div>
<div class="el-upload__tip">jpg/png格式 图片大小不能超过20KB</div>
</template>
<img v-if="dialogType === 'edit'" :src="formData.imageUrl" alt="预览图片"
style="width: 100px; height: 100px;">
<img
v-if="dialogType === 'edit'"
:src="formData.imageUrl"
alt="预览图片"
style="width: 100px; height: 100px"
/>
</el-upload>
</template>
<template #isDefault="{ formData }">
<el-radio-group v-model="formData.isDefault" v-if="dialogType === 'edit'">
<el-radio :value="1" ></el-radio>
<el-radio :value="1"></el-radio>
<el-radio :value="2"></el-radio>
</el-radio-group>
</template>
</VarietyForm>
</VarietyDialog>
<!-- dialog表格 -->
</template>
<script setup lang="ts">
@ -66,7 +93,12 @@ import { search, tableColumns, DialogFormItem } from './options'
import { rules } from './rules'
//
import { getVarietyListApi, getTradeGroupListApi, editVarietyApi, createVarietyApi } from '@/api/modules/trade/variety'
import {
getVarietyListApi,
getTradeGroupListApi,
editVarietyApi,
createVarietyApi,
} from '@/api/modules/trade/variety'
//
import { uploadImageApi } from '@/api/modules/upload'
@ -145,7 +177,7 @@ const varietyFormRef = ref<any>()
const varietyFormRules = ref(rules())
const dialogFormItemOptions = ref(DialogFormItem)
const varietyFormOptionsMap = ref({
tradeGroup: [],
group_id: [],
type: [
{
label: '外汇',
@ -220,7 +252,7 @@ const getVarietyList = async () => {
//
const getTradeGroupList = async () => {
const data = await getTradeGroupListApi()
varietyFormOptionsMap.value.tradeGroup = data.map((item: any) => ({
varietyFormOptionsMap.value.group_id = data.map((item: any) => ({
label: item.name,
value: item.id,
}))
@ -249,11 +281,11 @@ const handleReset = () => {
const handleEdit = () => {
getTradeGroupList()
const row = selectedRow.value;
const row = selectedRow.value
varietyForm.value = {
...row,
id: row.id,
groupId: row.group.id,
group_id: row.group_id || row.group.id,
//
prepaymentHedge: row.bail_hedge,
//
@ -268,11 +300,12 @@ const handleEdit = () => {
isDefault: row.is_default,
} as any
console.log('varietyForm.value', varietyForm.value)
//
dialogVisible.value = true
dialogTitle.value = '编辑合约品种'
dialogType.value = 'edit'
}
const handleAdd = () => {
@ -328,42 +361,42 @@ const handleUpload = async (options: any) => {
// + 20KB = 20 * 1024
const beforeUpload = (file: File) => {
//
const fileName = file.name.toLowerCase();
const isJpgOrPng = fileName.endsWith('.jpg') || fileName.endsWith('.jpeg') || fileName.endsWith('.png');
const fileName = file.name.toLowerCase()
const isJpgOrPng =
fileName.endsWith('.jpg') || fileName.endsWith('.jpeg') || fileName.endsWith('.png')
if (!isJpgOrPng) {
ElMessage.error('上传图片只能是 JPG/PNG 格式,且必须包含后缀名!');
return false;
ElMessage.error('上传图片只能是 JPG/PNG 格式,且必须包含后缀名!')
return false
}
// MIME
const isTypeValid = file.type === 'image/jpeg' || file.type === 'image/png';
const isTypeValid = file.type === 'image/jpeg' || file.type === 'image/png'
if (!isTypeValid) {
ElMessage.error('图片MIME类型不正确请重新选择!');
return false;
ElMessage.error('图片MIME类型不正确请重新选择!')
return false
}
// (20KB)
const isSizeValid = file.size / 1024 < 20;
const isSizeValid = file.size / 1024 < 20
if (!isSizeValid) {
ElMessage.error('图片大小不能超过 20KB!');
return false;
ElMessage.error('图片大小不能超过 20KB!')
return false
}
return true;
return true
}
/**
* @description: 定义弹窗方法
*/
const handleSubmit = async () => {
await varietyFormRef.value?.validate()
console.log(varietyForm.value)
const params = {
id: varietyForm.value.id,
code: varietyForm.value.varietyCode,
name: varietyForm.value.varietyName,
group_id: varietyForm.value.tradeGroup,
point_diff: varietyForm.value.minPoint,
fee_inventory_short: varietyForm.value.shortStockFee,
status: varietyForm.value.tradeStatus,
@ -381,16 +414,20 @@ const handleSubmit = async () => {
type: Number(varietyForm.value.type),
image: varietyForm.value.imageUrl,
fee_inventory_time: varietyForm.value.feeInventoryTime,
group_id: varietyForm.value.group_id,
}
console.log(params)
if (dialogType.value === 'edit') {
console.log(params)
await editVarietyApi({ ...params, group_id: selectedRow.value.group.id, is_default: varietyForm.value.isDefault })
getVarietyList()
await editVarietyApi({
...params,
is_default: varietyForm.value.isDefault,
})
await getVarietyList()
} else {
await createVarietyApi({ ...params })
getVarietyList()
await getVarietyList()
}
dialogVisible.value = false
}

View File

@ -51,7 +51,7 @@ export const DialogFormItem = [
// 编号
{ prop: 'varietyCode', label: '编号', type: 'input' as const, placeholder: '请输入编号' },
// 交易分组
{ prop: 'tradeGroup', label: '交易分组', type: 'select' as const, placeholder: '请选择交易分组' },
{ prop: 'group_id', label: '交易分组', type: 'select' as const, placeholder: '请选择交易分组' },
// 最大点差
{ prop: 'maxPoint', label: '最大点差', type: 'input' as const, placeholder: '请输入最大点差' },
// 最小点差
@ -110,7 +110,9 @@ export const DialogFormItem = [
{ prop: 'type', label: '类型', type: 'select' as const, placeholder: '请选择类型' },
// 库存费收取时间
{
prop: 'feeInventoryTime', label: '库存费收取时间', type: 'time' as const,
prop: 'feeInventoryTime',
label: '库存费收取时间',
type: 'time' as const,
valueFormat: 'HH:mm:ss',
isRange: false,
},

View File

@ -38,89 +38,78 @@ const validateMaxFiveDecimals = (fieldName: string) => {
export const rules = (): FormRules => {
return {
// 名称
varietyName: [
{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }
],
varietyName: [{ required: true, message: '请输入名称', trigger: ['blur', 'change'] }],
// 编号
varietyCode: [
{ required: true, message: '请输入编号', trigger: ['blur', 'change'] }
],
varietyCode: [{ required: true, message: '请输入编号', trigger: ['blur', 'change'] }],
// 所属交易时间
tradeTime: [
{ required: true, message: '请选择交易时间', trigger: ['blur', 'change'] }
],
tradeTime: [{ required: true, message: '请选择交易时间', trigger: ['blur', 'change'] }],
// 最大点差
maxPoint: [
{ required: true, message: '请输入最大点差', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('最大点差'), trigger: ['blur', 'change'] }
{ validator: validateMaxFiveDecimals('最大点差'), trigger: ['blur', 'change'] },
],
// 最小点差
minPoint: [
{ required: true, message: '请输入最小点差', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('最小点差')}
{ validator: validateMaxFiveDecimals('最小点差') },
],
// 合约大小
contractSize: [
{ required: true, message: '请输入合约大小', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('合约大小')}
{ validator: validateMaxFiveDecimals('合约大小') },
],
// 多头库存费
longStockFee: [
{ required: true, message: '请输入多头库存费', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('多头库存费')}
{ validator: validateMaxFiveDecimals('多头库存费') },
],
// 空头库存费
shortStockFee: [
{ required: true, message: '请输入空头库存费', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('空头库存费')}
{ validator: validateMaxFiveDecimals('空头库存费') },
],
// 预付款对冲
prepaymentHedge: [
{ required: true, message: '请输入预付款对冲', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('预付款对冲')}
{ validator: validateMaxFiveDecimals('预付款对冲') },
],
// 预付款百分比
prepaymentPercent: [
{ required: true, message: '请输入预付款百分比', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('预付款百分比')}
{ validator: validateMaxFiveDecimals('预付款百分比') },
],
// 小数位
decimalPlaces: [
{ required: true, message: '请输入小数位', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('小数位')}
{ validator: validateMaxFiveDecimals('小数位') },
],
// 点差小数位
pointDecimalPlaces: [
{ required: true, message: '请输入点差小数位', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('点差小数位')}
{ validator: validateMaxFiveDecimals('点差小数位') },
],
// 止盈水平
profitLevel: [
{ required: true, message: '请输入止盈水平', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('止盈水平')}
{ validator: validateMaxFiveDecimals('止盈水平') },
],
// 单位
unit: [
{ required: true, message: '请输入单位', trigger: ['blur', 'change'] }
],
unit: [{ required: true, message: '请输入单位', trigger: ['blur', 'change'] }],
// 最小波动
minFlux: [
{ required: true, message: '请输入最小波动', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('最小波动')}
{ validator: validateMaxFiveDecimals('最小波动') },
],
// 类型
type: [
{ required: true, message: '请选择类型', trigger: ['blur', 'change'] }
],
type: [{ required: true, message: '请选择类型', trigger: ['blur', 'change'] }],
// 上传图片
imageUrl: [
{ required: true, message: '请上传图片', trigger: ['blur', 'change'] }
],
imageUrl: [{ required: true, message: '请上传图片', trigger: ['blur', 'change'] }],
// 库存费收取时间
feeInventoryTime: [
{ required: true, message: '请选择库存费收取时间', trigger: ['blur', 'change'] }
{ required: true, message: '请选择库存费收取时间', trigger: ['blur', 'change'] },
],
group_id: [{ required: true, message: '请选择交易分组', trigger: ['blur', 'change'] }],
}
}