|
|
@@ -0,0 +1,239 @@
|
|
|
+<template>
|
|
|
+ <lay-card class="custom-card">
|
|
|
+ <template v-slot:title>
|
|
|
+ <span class="card-title">币对筛选器</span>
|
|
|
+ </template>
|
|
|
+ <template v-slot:body>
|
|
|
+ <div class="custom-form-layout">
|
|
|
+ <div class="custom-checkbox">
|
|
|
+ <div class="label">交易所</div>
|
|
|
+ <div class="checkbox-group">
|
|
|
+ <div class="checkbox-wp">
|
|
|
+ <lay-checkcard-group v-model="pageParams.exchanges">
|
|
|
+ <lay-checkcard value="gate_usdt_swap" title="gate_usdt_swap" />
|
|
|
+ <lay-checkcard value="bitget_usdt_swap" title="bitget_usdt_swap" />
|
|
|
+ </lay-checkcard-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="custom-checkbox">
|
|
|
+ <div class="label">参考时间</div>
|
|
|
+ <div class="checkbox-group">
|
|
|
+ <div class="checkbox-wp">
|
|
|
+ <lay-input v-model="pageParams.minute_time_range" placeholder="单位(分钟)" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="custom-card-checkbox">
|
|
|
+ <div class="label">指标模式</div>
|
|
|
+ <div class="checkbox-group">
|
|
|
+ <div class="checkbox-wp">
|
|
|
+ <lay-radio-group name="action" v-model="pageParams.mode">
|
|
|
+ <lay-radio value="or">或</lay-radio>
|
|
|
+ <lay-radio value="and">与</lay-radio>
|
|
|
+ </lay-radio-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="custom-card-checkbox">
|
|
|
+ <div class="label">指标</div>
|
|
|
+ <div class="checkbox-group">
|
|
|
+ <div class="checkbox-wp">
|
|
|
+ <lay-checkbox name="like" skin="primary" v-model="pageParams.rise" />
|
|
|
+ <span>上涨幅度大于</span><lay-input v-model="pageParams.rise_value" size="xs" class="checkbox-input" /><span>%</span>
|
|
|
+ </div>
|
|
|
+ <div class="checkbox-wp">
|
|
|
+ <lay-checkbox name="like" skin="primary" v-model="pageParams.rise_abs" />
|
|
|
+ <span>涨跌幅度绝对值大于</span><lay-input v-model="pageParams.rise_abs_value" size="xs" class="checkbox-input" /><span>%</span>
|
|
|
+ </div>
|
|
|
+ <div class="checkbox-wp">
|
|
|
+ <lay-checkbox name="like" skin="primary" v-model="pageParams.volume" />
|
|
|
+ <span>交易量大于</span><lay-input size="xs" v-model="pageParams.volume_value" class="checkbox-input" /><span>百万</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-button-wp">
|
|
|
+ <lay-button @click="getPageInfo()">搜索</lay-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <lay-table :page="tablePage" :columns="columns" resize :data-source="dataShowSource" :loading="pageConfig.loading" @change="handleCurrentChange" @sortChange="handleSortChange">
|
|
|
+ <template v-slot:rise="{ row }">
|
|
|
+ <div>
|
|
|
+ <div v-for="(value, key) of row.rise">{{ key }}:{{ value }}%</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-slot:volume="{ row }">
|
|
|
+ <div>
|
|
|
+ <div v-for="(value, key) of row.volume">{{ key }}:{{ value }}M</div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-slot:operator="{ row }">
|
|
|
+ <div>
|
|
|
+ <!-- <TableButton v-for="(_value, key) of row.rise" v-if="apiList?.includes('/ia/get_symbols_by_filter')" text="查看MSV" @click="toJump(row.symbol, key)" /> -->
|
|
|
+ <TableButton v-for="(_value, key) of row.rise" :text="`查看 ${key} MSV`" @click="toJump(row.symbol, key)" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </lay-table>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </lay-card>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup name="IndicatorSybmolFilter">
|
|
|
+import { ref, reactive } from "vue";
|
|
|
+import { useRouter } from "vue-router";
|
|
|
+import TableButton from "@/components/TableButton.vue";
|
|
|
+import { get_symbols_by_filter } from "@/api";
|
|
|
+
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+const apiList = ref(window.sessionStorage.getItem("_4L_API_LIST"));
|
|
|
+
|
|
|
+interface PageConfig {
|
|
|
+ loading: boolean;
|
|
|
+}
|
|
|
+
|
|
|
+let pageConfig: PageConfig = reactive({
|
|
|
+ loading: false,
|
|
|
+});
|
|
|
+
|
|
|
+interface FormItem {
|
|
|
+ mode?: string;
|
|
|
+ exchanges?: Array<string>;
|
|
|
+ minute_time_range?: string;
|
|
|
+ rise?: string;
|
|
|
+ rise_value?: string;
|
|
|
+ rise_abs?: string;
|
|
|
+ rise_abs_value?: string;
|
|
|
+ volume?: string;
|
|
|
+ volume_value?: string;
|
|
|
+}
|
|
|
+const pageParams: FormItem = reactive({ exchanges: ["gate_usdt_swap", "bitget_usdt_swap"], mode: "or", minute_time_range: "240" });
|
|
|
+
|
|
|
+interface TablePage {
|
|
|
+ current: number;
|
|
|
+ limit: number;
|
|
|
+ total: number;
|
|
|
+}
|
|
|
+const tablePage: TablePage = reactive({ current: 1, limit: 20, total: 0, limits: [20, 50, 100, 200, 500] });
|
|
|
+
|
|
|
+const columns = ref([
|
|
|
+ { title: "币对", key: "symbol" },
|
|
|
+ { title: "上涨幅度", key: "rise", customSlot: "rise", sort: "desc" },
|
|
|
+ { title: "交易量", key: "volume", customSlot: "volume", sort: "desc" },
|
|
|
+ { title: "操作", width: "200", key: "operator", customSlot: "operator" },
|
|
|
+]);
|
|
|
+let dataSource = ref<any>([]);
|
|
|
+let dataShowSource = ref<any>([]);
|
|
|
+let dataSortSource = ref<any>([]);
|
|
|
+
|
|
|
+// 请求交易所列表
|
|
|
+const getPageInfo = () => {
|
|
|
+ pageConfig.loading = true;
|
|
|
+ tablePage.current = 1;
|
|
|
+ tablePage.total = 0;
|
|
|
+ const params = {
|
|
|
+ mode: pageParams.mode,
|
|
|
+ exchanges: pageParams.exchanges,
|
|
|
+ minute_time_range: pageParams.minute_time_range,
|
|
|
+ filters: handleFilters(),
|
|
|
+ };
|
|
|
+ get_symbols_by_filter(params, (data: any) => {
|
|
|
+ pageConfig.loading = false;
|
|
|
+ if (data.code == 200) {
|
|
|
+ tablePage.total = data.data.length;
|
|
|
+ dataSource.value = data.data;
|
|
|
+ dataSortSource.value = data.data;
|
|
|
+ dataShowSource.value = [...data.data.slice((tablePage.current - 1) * tablePage.limit, tablePage.current * tablePage.limit)];
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+const handleFilters = () => {
|
|
|
+ let result = [];
|
|
|
+ if (pageParams.rise) result.push({ target: "R", value: pageParams.rise_value });
|
|
|
+ if (pageParams.rise_abs) result.push({ target: "ROA", value: pageParams.rise_abs_value });
|
|
|
+ if (pageParams.volume) result.push({ target: "V", value: pageParams.volume_value });
|
|
|
+ return result.length ? result : undefined;
|
|
|
+};
|
|
|
+getPageInfo();
|
|
|
+
|
|
|
+const toJump = (symbol: string, exchange: any) => {
|
|
|
+ router.push({ path: "/indicator/msv", query: { symbol, exchange } });
|
|
|
+};
|
|
|
+
|
|
|
+// 分页设置
|
|
|
+const handleCurrentChange = (val: any) => {
|
|
|
+ dataShowSource.value = [...dataSortSource.value.slice((val.current - 1) * val.limit, val.current * val.limit)];
|
|
|
+};
|
|
|
+
|
|
|
+// 排序
|
|
|
+const handleSortChange = (key: any, sort: any) => {
|
|
|
+ if (!sort) {
|
|
|
+ dataSortSource.value = [...dataSource.value];
|
|
|
+ dataShowSource.value = [...dataSource.value.slice((tablePage.current - 1) * tablePage.limit, tablePage.current * tablePage.limit)];
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ dataSortSource.value = [...dataSource.value].sort((a: any, b: any) => {
|
|
|
+ let maxA = -9999999;
|
|
|
+ let maxB = -9999999;
|
|
|
+ Object.values(a[key]).map((item) => (maxA = Number(item) > maxA ? Number(item) : maxA));
|
|
|
+ Object.values(b[key]).map((item) => (maxB = Number(item) > maxB ? Number(item) : maxB));
|
|
|
+ return maxA - maxB;
|
|
|
+ });
|
|
|
+ if (sort == "desc") dataSortSource.value.reverse();
|
|
|
+ dataShowSource.value = [...dataSortSource.value.slice((tablePage.current - 1) * tablePage.limit, tablePage.current * tablePage.limit)];
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.custom-form-layout {
|
|
|
+ .custom-card-checkbox,
|
|
|
+ .custom-checkbox {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 16px;
|
|
|
+ padding-right: 20px;
|
|
|
+ .label {
|
|
|
+ display: flex;
|
|
|
+ padding-right: 15px;
|
|
|
+ }
|
|
|
+ .checkbox-group {
|
|
|
+ display: flex;
|
|
|
+ .checkbox-wp {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-right: 10px;
|
|
|
+ line-height: 38px;
|
|
|
+ :deep(.layui-checkbox-label) {
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+ :deep(.layui-form-radio) {
|
|
|
+ margin-top: 0;
|
|
|
+ }
|
|
|
+ :deep(.layui-checkcard) {
|
|
|
+ padding: 0 10px;
|
|
|
+ width: auto;
|
|
|
+ margin: 0 10px 0 0;
|
|
|
+ .layui-checkcard-content {
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .checkbox-input {
|
|
|
+ width: 40px;
|
|
|
+ }
|
|
|
+ &:last-child {
|
|
|
+ margin-right: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .custom-card-checkbox {
|
|
|
+ .checkbox-wp {
|
|
|
+ padding: 0 20px;
|
|
|
+ border: 1px solid #d9d9d9;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|