|
@@ -1,338 +0,0 @@
|
|
|
-<template>
|
|
|
|
|
- <lay-card class="custom-card">
|
|
|
|
|
- <template v-slot:title>
|
|
|
|
|
- <span class="card-title">CTA机器人管理</span>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-slot:extra>
|
|
|
|
|
- <lay-button class="card-button" @click="handleUpdate(0)">添加</lay-button>
|
|
|
|
|
- </template>
|
|
|
|
|
-
|
|
|
|
|
- <template v-slot:body>
|
|
|
|
|
- <div class="custom-form-layout">
|
|
|
|
|
- <lay-form class="form-wp" :model="pageParams" mode="inline" size="sm">
|
|
|
|
|
- <lay-form-item label="名称" prop="name">
|
|
|
|
|
- <lay-input v-model="pageParams.name" />
|
|
|
|
|
- </lay-form-item>
|
|
|
|
|
- <lay-form-item label="币对" prop="symbol">
|
|
|
|
|
- <lay-input v-model="pageParams.symbol" />
|
|
|
|
|
- </lay-form-item>
|
|
|
|
|
- <lay-form-item label="状态" prop="robotState">
|
|
|
|
|
- <lay-select v-model="pageParams.robotState" :show-search="true" allowClear>
|
|
|
|
|
- <lay-select-option v-for="(value, key) of ROBOT_STATUS" :value="key" :label="value" />
|
|
|
|
|
- </lay-select>
|
|
|
|
|
- </lay-form-item>
|
|
|
|
|
- <div class="form-button-wp">
|
|
|
|
|
- <lay-button @click="getPageInfo(true)">搜索</lay-button>
|
|
|
|
|
- </div>
|
|
|
|
|
- </lay-form>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="custom-operator-wp padding-bottom-10">
|
|
|
|
|
- <!-- <div class="custom-group collect-wp" v-html="collectInfo" /> -->
|
|
|
|
|
- <div class="custom-group">
|
|
|
|
|
- <lay-space>
|
|
|
|
|
- <!-- <lay-button v-if="apiList?.includes('/robot/submitStatus')" :border="'green'" size="xs" @click="handleStatus(selectedKeys, 'RUN')">开机</lay-button> -->
|
|
|
|
|
- <!-- <lay-button v-if="apiList?.includes('/robot/submitStatus')" :border="'red'" size="xs" @click="handleStatus(selectedKeys, 'STOP')">停机</lay-button> -->
|
|
|
|
|
- <lay-button border="green" size="xs" @click="handleRrestoration(selectedKeys)">复位余额</lay-button>
|
|
|
|
|
- </lay-space>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div>
|
|
|
|
|
- <lay-table :page="tablePage" :columns="columns" resize id="id" :data-source="dataSource" v-model:selected-keys="selectedKeys" :loading="pageConfig.loading" @change="handleCurrentChange">
|
|
|
|
|
- <template v-slot:name="{ row }">
|
|
|
|
|
- <span class="normal-color" @click="jumpDetail(row)">{{ row.name }}</span>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-slot:earningRate="{ row }">
|
|
|
|
|
- <span :class="{ 'primary-color': row.nowAmount - row.startAmount > 0, 'danger-color': row.nowAmount - row.startAmount < 0 }">
|
|
|
|
|
- {{ (((row.nowAmount - row.startAmount) / (row.startAmount || 1)) * 100).toFixed(2) || 0 }}%
|
|
|
|
|
- </span>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-slot:startAmount="{ row }">
|
|
|
|
|
- {{ row.startAmount.toFixed(2) || 0 }}
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-slot:nowAmount="{ row }">
|
|
|
|
|
- {{ row.nowAmount.toFixed(2) || 0 }}
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-slot:configs="{ row }">
|
|
|
|
|
- <lay-tooltip :content="`资金比例:${row.fundRatio * 100}%;账户止损比例:${row.stopLoss * 100}%`">
|
|
|
|
|
- <div class="ellipsis-2" @click="handleUpdate(row)">
|
|
|
|
|
- {{ `资金比例:${row.fundRatio * 100}%;账户止损比例:${row.stopLoss * 100}%` }}
|
|
|
|
|
- </div>
|
|
|
|
|
- </lay-tooltip>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-slot:status="{ row }">
|
|
|
|
|
- <lay-space v-if="row.status">
|
|
|
|
|
- <lay-badge type="dot" theme="blue" ripple />
|
|
|
|
|
- <span>{{ ROBOT_STATUS[row.status] }}</span>
|
|
|
|
|
- </lay-space>
|
|
|
|
|
- <lay-space v-else-if="!row.status">
|
|
|
|
|
- <lay-badge type="dot" />
|
|
|
|
|
- <span>{{ ROBOT_STATUS[row.status] }}</span>
|
|
|
|
|
- </lay-space>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-slot:updateTime="{ row }">
|
|
|
|
|
- <span>{{ timeConverts(row.updateTime) }}</span>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-slot:operator="{ row }">
|
|
|
|
|
- <lay-space>
|
|
|
|
|
- <TableButton :text="row.status ? '关机' : '开机'" :type="row.status ? 'danger' : 'primary'" @click="handleStatus(row)" />
|
|
|
|
|
- <TableButton text="编辑" @click="handleUpdate(row)" />
|
|
|
|
|
- <TableButton text="更新余额" @click="refreshBalance(row)" />
|
|
|
|
|
- <TableButton v-if="!row.status" type="danger" text="删除" @click="handleDelete(row)" />
|
|
|
|
|
- </lay-space>
|
|
|
|
|
- </template>
|
|
|
|
|
- </lay-table>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="custom-operator-wp padding-top-10">
|
|
|
|
|
- <!-- <div class="custom-group collect-wp" v-html="collectInfo" /> -->
|
|
|
|
|
- <div class="custom-group">
|
|
|
|
|
- <lay-space>
|
|
|
|
|
- <!-- <lay-button v-if="apiList?.includes('/robot/submitStatus')" :border="'green'" size="xs" @click="handleStatus(selectedKeys, 'RUN')">开机</lay-button> -->
|
|
|
|
|
- <!-- <lay-button v-if="apiList?.includes('/robot/submitStatus')" :border="'red'" size="xs" @click="handleStatus(selectedKeys, 'STOP')">停机</lay-button> -->
|
|
|
|
|
- <lay-button border="green" size="xs" @click="handleRrestoration(selectedKeys)">复位余额</lay-button>
|
|
|
|
|
- </lay-space>
|
|
|
|
|
- </div>
|
|
|
|
|
- </div>
|
|
|
|
|
- </template>
|
|
|
|
|
- </lay-card>
|
|
|
|
|
- <Update ref="updateRef" />
|
|
|
|
|
-</template>
|
|
|
|
|
-
|
|
|
|
|
-<script lang="ts" setup name="BotCta">
|
|
|
|
|
-import { ref, reactive, getCurrentInstance, onActivated, onDeactivated } from "vue";
|
|
|
|
|
-import Update from "./components/Update.vue";
|
|
|
|
|
-import TableButton from "@/components/TableButton.vue";
|
|
|
|
|
-import { timeConverts } from "@/utils/index";
|
|
|
|
|
-import { get_cta_robot_list, delete_cta_robot, set_cta_robot_status, refresh_cta_robot_balance, restoration_cta_robot_balance } from "@/api";
|
|
|
|
|
-
|
|
|
|
|
-const ROBOT_STATUS: any = reactive({
|
|
|
|
|
- 0: "已停止",
|
|
|
|
|
- 1: "运行中",
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-const { proxy }: any = getCurrentInstance();
|
|
|
|
|
-const updateRef = ref();
|
|
|
|
|
-
|
|
|
|
|
-// const apiList = ref(window.sessionStorage.getItem("_4L_API_LIST"));
|
|
|
|
|
-
|
|
|
|
|
-interface PageConfig {
|
|
|
|
|
- loading: boolean;
|
|
|
|
|
- requestLoading: boolean;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-let pageConfig: PageConfig = reactive({
|
|
|
|
|
- loading: false,
|
|
|
|
|
- requestLoading: false,
|
|
|
|
|
-});
|
|
|
|
|
-
|
|
|
|
|
-interface FormItem {
|
|
|
|
|
- pageNum?: Number;
|
|
|
|
|
- pageSize?: Number;
|
|
|
|
|
- name?: String;
|
|
|
|
|
- symbol?: String;
|
|
|
|
|
- robotState?: String;
|
|
|
|
|
-}
|
|
|
|
|
-const pageParams: FormItem = reactive({ pageNum: 1, pageSize: 50 });
|
|
|
|
|
-
|
|
|
|
|
-interface TablePage {
|
|
|
|
|
- current: number;
|
|
|
|
|
- limit: number;
|
|
|
|
|
- total: number;
|
|
|
|
|
-}
|
|
|
|
|
-const tablePage: TablePage = reactive({ current: 1, limit: 50, total: 0, limits: [20, 50, 100, 200, 500] });
|
|
|
|
|
-const columns = ref([
|
|
|
|
|
- { title: "选项", width: "44px", type: "checkbox" },
|
|
|
|
|
- { title: "ID", width: "50px", key: "id" },
|
|
|
|
|
- { title: "名称", key: "name", customSlot: "name", ellipsisTooltip: true },
|
|
|
|
|
- { title: "账户", key: "accountName", ellipsisTooltip: true },
|
|
|
|
|
- { title: "币对", key: "symbol", align: "center", ellipsisTooltip: true },
|
|
|
|
|
- { title: "初始余额", width: "100px", key: "startAmount", customSlot: "startAmount",align: "center" },
|
|
|
|
|
- { title: "当前余额", width: "100px", key: "nowAmount", customSlot: "nowAmount",align: "center" },
|
|
|
|
|
- { title: "收益", width: "80px", key: "earningRate", customSlot: "earningRate", align: "center" },
|
|
|
|
|
- { title: "配置信息", width: "240px", key: "configs", customSlot: "configs" },
|
|
|
|
|
- { title: "状态", width: "90px", key: "status", customSlot: "status", align: "center" },
|
|
|
|
|
- { title: "IP", width: "120px", key: "serverName", ellipsisTooltip: true },
|
|
|
|
|
- // { title: "持仓信息", width: "80px", key: "posNum", customSlot: "posNum", align: "center", ellipsisTooltip: true },
|
|
|
|
|
- { title: "修改时间", width: "90px", key: "updateTime", customSlot: "updateTime", align: "center" },
|
|
|
|
|
- // { title: "所属人", width: "80px", key: "userName", align: "center", ellipsisTooltip: true },
|
|
|
|
|
- {
|
|
|
|
|
- title: "操作",
|
|
|
|
|
- width: "200px",
|
|
|
|
|
- customSlot: "operator",
|
|
|
|
|
- key: "operator",
|
|
|
|
|
- ignoreExport: true,
|
|
|
|
|
- },
|
|
|
|
|
-]);
|
|
|
|
|
-
|
|
|
|
|
-let dataSource = ref([]);
|
|
|
|
|
-let selectedKeys = ref([]);
|
|
|
|
|
-// let collectInfo = ref(`[0/0] 利润:<span class="primary-color">0(0%)</span> 初始:<span class="primary-color">0</span> 现有:<span class="primary-color">0</span>`);
|
|
|
|
|
-// let exchangeList = ref();
|
|
|
|
|
-let refreshAsBotInterval = ref();
|
|
|
|
|
-
|
|
|
|
|
-// 请求机器人列表
|
|
|
|
|
-const getPageInfo = (isSearch?: boolean, isRefresh?: boolean) => {
|
|
|
|
|
- if (isSearch) {
|
|
|
|
|
- pageParams.pageNum = 1;
|
|
|
|
|
- selectedKeys.value = [];
|
|
|
|
|
- pageConfig.requestLoading = false;
|
|
|
|
|
- }
|
|
|
|
|
- if (pageConfig.requestLoading) return;
|
|
|
|
|
-
|
|
|
|
|
- pageConfig.requestLoading = true;
|
|
|
|
|
- pageConfig.loading = true && !isRefresh;
|
|
|
|
|
- get_cta_robot_list(pageParams, (data: any) => {
|
|
|
|
|
- pageConfig.requestLoading = false;
|
|
|
|
|
- pageConfig.loading = false && !isRefresh;
|
|
|
|
|
- if (data.code == 200) {
|
|
|
|
|
- dataSource.value = data.data.list;
|
|
|
|
|
- tablePage.total = data.data.total;
|
|
|
|
|
- // handleShowInfo(data.data);
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-getPageInfo();
|
|
|
|
|
-
|
|
|
|
|
-const jumpDetail = (info: any) => {
|
|
|
|
|
- window.open(`/bot/cta/detail/${info.id}`);
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// const handleShowInfo = (info: any) => {
|
|
|
|
|
-// document.title = `[${info.runNum || 0}/${info.total || 0}] 利润:${info.income || 0}(${info.incomeRate || 0}%)
|
|
|
|
|
-// 初始:${info.startAmount || 0} 现有:${info.nowAmount || 0}`;
|
|
|
|
|
-// collectInfo.value = `[${info.runNum || 0}/${info.total || 0}] 利润:<span class="${info.income >= 0 ? "primary-color" : "danger-color"}">${info.income || 0}(${info.incomeRate || 0}%)</span>
|
|
|
|
|
-// 初始:<span class="primary-color">${info.startAmount || 0}</span> 现有:<span class="primary-color">${info.nowAmount || 0}</span>`;
|
|
|
|
|
-// };
|
|
|
|
|
-
|
|
|
|
|
-const handleStatus = async (value: any) => {
|
|
|
|
|
- let result = await proxy.$waitingConfirm(`是否确认${value.status ? "关机" : "开机"}?`);
|
|
|
|
|
- if (!result) return;
|
|
|
|
|
- let params = {
|
|
|
|
|
- id: value.id,
|
|
|
|
|
- status: value.status ? 0 : 1,
|
|
|
|
|
- };
|
|
|
|
|
- pageConfig.loading = true;
|
|
|
|
|
- set_cta_robot_status(params, (data: any) => {
|
|
|
|
|
- pageConfig.loading = false;
|
|
|
|
|
- if (data.code == 200) {
|
|
|
|
|
- proxy.$message(`修改成功!`);
|
|
|
|
|
- getPageInfo();
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const handleUpdate = async (value?: any) => {
|
|
|
|
|
- const result = await updateRef.value.show(value);
|
|
|
|
|
- if (result) getPageInfo();
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const handleRrestoration = async (value?: any) => {
|
|
|
|
|
- let result = await proxy.$waitingConfirm("是否确认复位机器人余额?");
|
|
|
|
|
- if (!result) return;
|
|
|
|
|
- let params = value;
|
|
|
|
|
- pageConfig.loading = true;
|
|
|
|
|
- await restoration_cta_robot_balance(params, (data: any) => {
|
|
|
|
|
- pageConfig.loading = false;
|
|
|
|
|
- if (data.code == 200) {
|
|
|
|
|
- proxy.$message(`更新成功!`);
|
|
|
|
|
- getPageInfo();
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 更新余额
|
|
|
|
|
-const refreshBalance = async (value?: any) => {
|
|
|
|
|
- let result = await proxy.$waitingConfirm("是否确认更新该机器人余额?");
|
|
|
|
|
- if (!result) return;
|
|
|
|
|
- let params = { id: value.id };
|
|
|
|
|
- pageConfig.loading = true;
|
|
|
|
|
- await refresh_cta_robot_balance(params, (data: any) => {
|
|
|
|
|
- pageConfig.loading = false;
|
|
|
|
|
- if (data.code == 200) {
|
|
|
|
|
- proxy.$message(`更新成功!`);
|
|
|
|
|
- getPageInfo();
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 删除机器人
|
|
|
|
|
-const handleDelete = async (value: any) => {
|
|
|
|
|
- let result = await proxy.$waitingConfirm("是否确认删除该机器人?");
|
|
|
|
|
- if (!result) return;
|
|
|
|
|
- let params = [value.id];
|
|
|
|
|
- pageConfig.loading = true;
|
|
|
|
|
- delete_cta_robot(params, (data: any) => {
|
|
|
|
|
- pageConfig.loading = false;
|
|
|
|
|
- if (data.code == 200) {
|
|
|
|
|
- proxy.$message(`删除成功!`);
|
|
|
|
|
- getPageInfo();
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-// 分页设置
|
|
|
|
|
-const handleCurrentChange = (val: any) => {
|
|
|
|
|
- pageParams.pageNum = val.current;
|
|
|
|
|
- pageParams.pageSize = val.limit;
|
|
|
|
|
- getPageInfo();
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-const startInterval = () => {
|
|
|
|
|
- clearInterval(refreshAsBotInterval.value);
|
|
|
|
|
- refreshAsBotInterval.value = setInterval(() => {
|
|
|
|
|
- getPageInfo(false, true);
|
|
|
|
|
- }, 10000);
|
|
|
|
|
-};
|
|
|
|
|
-startInterval();
|
|
|
|
|
-const closeInterval = () => {
|
|
|
|
|
- clearInterval(refreshAsBotInterval.value);
|
|
|
|
|
-};
|
|
|
|
|
-onActivated(() => {
|
|
|
|
|
- startInterval();
|
|
|
|
|
-});
|
|
|
|
|
-onDeactivated(() => {
|
|
|
|
|
- closeInterval();
|
|
|
|
|
- document.title = "4L CAPITAL";
|
|
|
|
|
-});
|
|
|
|
|
-</script>
|
|
|
|
|
-
|
|
|
|
|
-<style lang="scss" scoped>
|
|
|
|
|
-.custom-operator-wp {
|
|
|
|
|
- .custom-group {
|
|
|
|
|
- margin-right: 14px;
|
|
|
|
|
- display: inline-block;
|
|
|
|
|
- vertical-align: middle;
|
|
|
|
|
- }
|
|
|
|
|
- .collect-wp {
|
|
|
|
|
- line-height: 24px;
|
|
|
|
|
- padding: 0 4px;
|
|
|
|
|
- border: 1px solid var(--normal-color);
|
|
|
|
|
- color: var(--normal-color);
|
|
|
|
|
- :deep(.primary-color) {
|
|
|
|
|
- color: var(--primary-color);
|
|
|
|
|
- }
|
|
|
|
|
- :deep(.danger-color) {
|
|
|
|
|
- color: var(--danger-color);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-.ellipsis-2 {
|
|
|
|
|
- display: -webkit-box;
|
|
|
|
|
- -webkit-box-orient: vertical;
|
|
|
|
|
- overflow: hidden;
|
|
|
|
|
- line-break: anywhere;
|
|
|
|
|
- line-clamp: 2; /* 控制显示的行数 */
|
|
|
|
|
- -webkit-line-clamp: 2; /* 控制显示的行数 */
|
|
|
|
|
-}
|
|
|
|
|
-.custom-form-layout {
|
|
|
|
|
- font-size: 12px !important;
|
|
|
|
|
-}
|
|
|
|
|
-.primary-color {
|
|
|
|
|
- color: var(--primary-color);
|
|
|
|
|
-}
|
|
|
|
|
-.normal-color {
|
|
|
|
|
- color: var(--normal-color);
|
|
|
|
|
-}
|
|
|
|
|
-.danger-color {
|
|
|
|
|
- color: var(--danger-color);
|
|
|
|
|
-}
|
|
|
|
|
-</style>
|
|
|