Эх сурвалжийг харах

添加币对筛选器
添加机器人调参提示

DESKTOP-NE65RNK\Citrus_limon 1 жил өмнө
parent
commit
a77c8d69a3

+ 4 - 3
.env.development

@@ -1,5 +1,6 @@
 VITE_APP_ENV = development
 
-# VITE_API_BASE_URL = "http://4lapi.skyfffire.com"
-VITE_API_BASE_URL = "http://t4lapi.skyfffire.com"
-# VITE_API_BASE_URL = "http://192.168.1.5:18888"
+VITE_API_BASE_URL = "https://4lapi.skyfffire.com"
+# VITE_API_BASE_URL = "http://t4lapi.skyfffire.com"
+# VITE_API_BASE_URL = "http://192.168.1.5:18888"
+# VITE_API_BASE_URL = "http://183.249.84.29:18888"

+ 7 - 1
src/api/index.ts

@@ -421,12 +421,18 @@ export const delete_instruct_log = (params: any, callback: any) => {
 };
 
 // 情报中心
-// 情报中心-波动率指标
+// 情报中心-指标
 export const get_indicator = (params: any, callback: any) => {
   return http.request("/ia/get_indicator", "post", params).then((data) => {
     if (data) callback && callback(data);
   });
 };
+// 情报中心-币对筛选器
+export const get_symbols_by_filter = (params: any, callback: any) => {
+  return http.request("/ia/get_symbols_by_filter", "post", params).then((data) => {
+    if (data) callback && callback(data);
+  });
+};
 
 // 资金曲线
 // 资金曲线-按用户

+ 14 - 9
src/assets/css/index.scss

@@ -110,14 +110,11 @@ body,
           width: auto !important;
         }
       }
-      .form-button-wp {
-        vertical-align: top;
-        display: inline-block;
-      }
     }
-  }
-  .custom-operator-wp {
-    padding-bottom: 10px;
+    .form-button-wp {
+      vertical-align: top;
+      display: inline-block;
+    }
   }
 }
 
@@ -126,6 +123,13 @@ body,
   overflow-y: auto;
 }
 
+.padding-top-10 {
+  padding-top: 10px;
+}
+.padding-bottom-10 {
+  padding-bottom: 10px;
+}
+
 .width-500 {
   box-sizing: border-box;
   width: 500px;
@@ -292,8 +296,9 @@ body,
   }
 }
 
-.custom-form-layout{
-  .layui-input-inline{
+.custom-form-layout {
+  padding-bottom: 10px;
+  .layui-input-inline {
     width: auto;
   }
 }

+ 6 - 0
src/router/routes.ts

@@ -70,6 +70,12 @@ const routes: Array<RouteRecordRaw> = [
         component: () => import("@/views/indicator/msv/index.vue"),
         meta: { title: "波动率指标", keepAlive: true },
       },
+      {
+        path: "/indicator/sybmol_filter",
+        name: "IndicatorSybmolFilter",
+        component: () => import("@/views/indicator/sybmol_filter/index.vue"),
+        meta: { title: "币对筛选器", keepAlive: true },
+      },
       {
         path: "/statistic/balance_user",
         name: "StatisticBalanceUser",

+ 32 - 13
src/views/bot/manage/components/BatchUpdate.vue

@@ -5,37 +5,37 @@
         <lay-row space="10">
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="名称" prop="name">
-              <lay-input v-model="modelParams.name" />
+              <lay-input v-model="modelParams.name" placeholder="机器人名称" />
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="初始金额" prop="startAmount">
-              <lay-input v-model="modelParams.startAmount" />
+              <lay-input v-model="modelParams.startAmount" placeholder="初始金额" />
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="服务器" prop="serverId">
               <lay-select v-model="modelParams.serverId" :show-search="true">
-                <lay-select-option v-for="item in serverList" :value="item.id" :label="item.value" />
+                <lay-select-option v-for="item in serverList" :value="item.id" :label="item.value" placeholder="选择服务器" />
               </lay-select>
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="通讯端口" prop="callPort">
-              <lay-input v-model="modelParams.callPort" />
+              <lay-input v-model="modelParams.callPort" placeholder="通讯端口(不要填常用端口:1001、1002)" />
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="策略" prop="strategyId">
               <lay-select v-model="modelParams.strategyId" @change="strategyHandleChange">
-                <lay-select-option v-for="item in strategyList" :value="item.id" :label="item.value" />
+                <lay-select-option v-for="item in strategyList" :value="item.id" :label="item.value" placeholder="选择策略" />
               </lay-select>
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="策略版本" prop="strategyProgramId">
               <lay-select v-model="modelParams.strategyProgramId" @change="strategyProgramHandleChange">
-                <lay-select-option v-for="item in strategyProgramList" :value="item.id" :label="item.value" />
+                <lay-select-option v-for="item in strategyProgramList" :value="item.id" :label="item.value" placeholder="选择策略版本" />
               </lay-select>
             </lay-form-item>
           </lay-col>
@@ -43,19 +43,24 @@
             <template v-for="item in strategyParameterList">
               <lay-col md="12" sm="12" xs="24">
                 <lay-form-item :label="item.name" :prop="`robotConfigs.${item.code}`">
-                  <lay-input v-if="item.valType == 0" v-model="modelParams.robotConfigs[item.code]" @input="handleStringInput(item.code, $event)" />
-                  <lay-input v-if="item.valType == 1 && item.code != 'colo'" v-model="modelParams.robotConfigs[item.code]" @input="handleNmberInput(item.code, $event)" />
+                  <lay-input v-if="item.valType == 0" v-model="modelParams.robotConfigs[item.code]" @input="handleStringInput(item.code, $event)" :placeholder="PARAMS_ENUM[item.code]" />
+                  <lay-input
+                    v-if="item.valType == 1 && item.code != 'colo'"
+                    v-model="modelParams.robotConfigs[item.code]"
+                    @input="handleNmberInput(item.code, $event)"
+                    :placeholder="PARAMS_ENUM[item.code]"
+                  />
                   <lay-switch v-if="item.valType == 1 && item.code == 'colo'" onswitch-value="1" unswitch-value="0" v-model="modelParams.robotConfigs[item.code]" />
                   <lay-switch v-if="item.valType == 2" v-model="modelParams.robotConfigs[item.code]" />
-                  <lay-select v-if="item.valType == 3" v-model="modelParams.robotConfigs[item.code]" :show-search="true">
+                  <lay-select v-if="item.valType == 3" v-model="modelParams.robotConfigs[item.code]" :show-search="true" :placeholder="PARAMS_ENUM[item.code]">
                     <lay-select-option v-for="items in item.contentVal.split(',')" :value="items" :label="items" />
                   </lay-select>
-                  <lay-select v-if="item.valType == 5" v-model="modelParams.robotConfigs[item.code]" :options="apikeyList" :show-search="true" />
+                  <lay-select v-if="item.valType == 5" v-model="modelParams.robotConfigs[item.code]" :options="apikeyList" :show-search="true" :placeholder="PARAMS_ENUM[item.code]" />
                 </lay-form-item>
-                <lay-form-item v-if="item.code == 'open'" label="开仓递增" :prop="`robotConfigs.openIntervals`">
+                <lay-form-item v-if="item.code == 'open'" label="开仓递增" :prop="`robotConfigs.openIntervals`" :placeholder="PARAMS_ENUM[item.code]">
                   <lay-input v-model="modelParams.robotConfigs.openIntervals" />
                 </lay-form-item>
-                <lay-form-item v-if="item.code == 'close'" label="平仓递增" :prop="`robotConfigs.closeIntervals`">
+                <lay-form-item v-if="item.code == 'close'" label="平仓递增" :prop="`robotConfigs.closeIntervals`" :placeholder="PARAMS_ENUM[item.code]">
                   <lay-input v-model="modelParams.robotConfigs.closeIntervals" />
                 </lay-form-item>
               </lay-col>
@@ -75,6 +80,20 @@ import Decimal from "decimal.js";
 import { ref, reactive, getCurrentInstance } from "vue";
 import { update_robot_batch, get_server_select, get_strategy_select, get_strategy_program_select, get_strategy_parameter_select, get_apikey_select, set_robot_status } from "@/api";
 
+const PARAMS_ENUM: any = {
+  open: "挂单距离百分比",
+  close: "平仓距离百分比",
+  lever_rate: "杠杆倍数",
+  stop_loss: "百分比最大回撤",
+  pair: "不带USDT会自动补齐",
+  exchange: "交易盘口",
+  ref_pair: "不带USDT会自动补齐",
+  ref_exchange: "参考盘口",
+  grid: "网格数量",
+  hold_coin: "现货底仓",
+  account: "账户",
+};
+
 const { proxy }: any = getCurrentInstance();
 
 const modelFormRef = ref();
@@ -118,7 +137,7 @@ const show = async (params?: any) => {
   modelConfig.visible = true;
   modelConfig.title = "批量设置机器人";
 
-  modelParams.value = { strategyId: params[0].strategyId, strategyProgramId: params[0].strategyProgramId, robotConfigs: {} };
+  modelParams.value = { strategyId: params[0].strategyId, strategyProgramId: params[0].strategyProgramId, robotConfigs: { openIntervals: "0.00", closeIntervals: "0.00" } };
   botDetailList.value = params;
   strategyHandleChange(modelParams.value.strategyId);
   strategyProgramHandleChange(modelParams.value.strategyProgramId);

+ 31 - 11
src/views/bot/manage/components/Update.vue

@@ -5,37 +5,37 @@
         <lay-row space="10">
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="名称" prop="name">
-              <lay-input v-model="modelParams.name" />
+              <lay-input v-model="modelParams.name" placeholder="机器人名称" />
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="初始金额" prop="startAmount">
-              <lay-input v-model="modelParams.startAmount" />
+              <lay-input v-model="modelParams.startAmount" placeholder="初始金额" />
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="服务器" prop="serverId">
               <lay-select v-model="modelParams.serverId" :show-search="true">
-                <lay-select-option v-for="item in serverList" :value="item.id" :label="item.value" />
+                <lay-select-option v-for="item in serverList" :value="item.id" :label="item.value" placeholder="选择服务器" />
               </lay-select>
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="通讯端口" prop="callPort">
-              <lay-input v-model="modelParams.callPort" />
+              <lay-input v-model="modelParams.callPort" placeholder="通讯端口(1001、1002)" />
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="策略" prop="strategyId">
               <lay-select v-model="modelParams.strategyId" @change="strategyHandleChange">
-                <lay-select-option v-for="item in strategyList" :value="item.id" :label="item.value" />
+                <lay-select-option v-for="item in strategyList" :value="item.id" :label="item.value" placeholder="选择策略" />
               </lay-select>
             </lay-form-item>
           </lay-col>
           <lay-col md="12" sm="12" xs="24">
             <lay-form-item label="策略版本" prop="strategyProgramId">
               <lay-select v-model="modelParams.strategyProgramId" @change="strategyProgramHandleChange">
-                <lay-select-option v-for="item in strategyProgramList" :value="item.id" :label="item.value" />
+                <lay-select-option v-for="item in strategyProgramList" :value="item.id" :label="item.value" placeholder="选择策略版本" />
               </lay-select>
             </lay-form-item>
           </lay-col>
@@ -43,14 +43,19 @@
             <template v-for="item in strategyParameterList">
               <lay-col md="12" sm="12" xs="24">
                 <lay-form-item :label="item.name" :prop="`robotConfigs.${item.code}`">
-                  <lay-input v-if="item.valType == 0" v-model="modelParams.robotConfigs[item.code]" @input="handleStringInput(item.code, $event)" />
-                  <lay-input v-if="item.valType == 1 && item.code != 'colo'" v-model="modelParams.robotConfigs[item.code]" @input="handleNmberInput(item.code, $event)" />
+                  <lay-input v-if="item.valType == 0" v-model="modelParams.robotConfigs[item.code]" @input="handleStringInput(item.code, $event)" :placeholder="PARAMS_ENUM[item.code]" />
+                  <lay-input
+                    v-if="item.valType == 1 && item.code != 'colo'"
+                    v-model="modelParams.robotConfigs[item.code]"
+                    @input="handleNmberInput(item.code, $event)"
+                    :placeholder="PARAMS_ENUM[item.code]"
+                  />
                   <lay-switch v-if="item.valType == 1 && item.code == 'colo'" onswitch-value="1" unswitch-value="0" v-model="modelParams.robotConfigs[item.code]" />
                   <lay-switch v-if="item.valType == 2" v-model="modelParams.robotConfigs[item.code]" />
                   <lay-select v-if="item.valType == 3" v-model="modelParams.robotConfigs[item.code]" :show-search="true">
-                    <lay-select-option v-for="items in item.contentVal.split(',')" :value="items" :label="items" />
+                    <lay-select-option v-for="items in item.contentVal.split(',')" :value="items" :label="items" :placeholder="PARAMS_ENUM[item.code]" />
                   </lay-select>
-                  <lay-select v-if="item.valType == 5" v-model="modelParams.robotConfigs[item.code]" :options="apikeyList" :show-search="true" />
+                  <lay-select v-if="item.valType == 5" v-model="modelParams.robotConfigs[item.code]" :options="apikeyList" :show-search="true" :placeholder="PARAMS_ENUM[item.code]" />
                 </lay-form-item>
               </lay-col>
             </template>
@@ -66,8 +71,23 @@
 
 <script lang="ts" setup>
 import { ref, reactive, getCurrentInstance } from "vue";
+import Decimal from "decimal.js";
 import { add_robot, update_robot, get_server_select, get_strategy_select, get_strategy_program_select, get_strategy_parameter_select, get_apikey_select, set_robot_status } from "@/api";
 
+const PARAMS_ENUM: any = {
+  open: "挂单距离百分比",
+  close: "平仓距离百分比",
+  lever_rate: "杠杆倍数",
+  stop_loss: "百分比最大回撤",
+  pair: "不带USDT会自动补齐",
+  exchange: "交易盘口",
+  ref_pair: "不带USDT会自动补齐",
+  ref_exchange: "参考盘口",
+  grid: "网格数量",
+  hold_coin: "现货底仓",
+  account: "账户",
+};
+
 const { proxy }: any = getCurrentInstance();
 
 const modelFormRef = ref();
@@ -195,7 +215,7 @@ const handleStringInput = (code: string, value: any) => {
 };
 const handleNmberInput = (code: string, value: any) => {
   if (code == "lever_rate") {
-    modelParams.value.robotConfigs.stop_loss = Number(value) / 100 > 0.06 ? 0.06 : Number(value) / 100;
+    modelParams.value.robotConfigs.stop_loss = new Decimal(value).dividedBy(100) > new Decimal(0.06) ? 0.06 : new Decimal(value).dividedBy(100);
   }
 };
 

+ 2 - 3
src/views/bot/manage/index.vue

@@ -38,7 +38,7 @@
           </div>
         </lay-form>
       </div>
-      <div class="custom-operator-wp">
+      <div class="custom-operator-wp padding-bottom-10">
         <div class="custom-group collect-wp" v-html="collectInfo" />
         <div class="custom-group">
           <lay-space>
@@ -127,7 +127,7 @@
           </template>
         </lay-table>
       </div>
-      <div class="custom-operator-wp">
+      <div class="custom-operator-wp padding-top-10">
         <div class="custom-group collect-wp" v-html="collectInfo" />
         <div class="custom-group">
           <lay-space>
@@ -451,7 +451,6 @@ onBeforeUnmount(() => {
 <style lang="scss" scoped>
 .custom-operator-wp {
   .custom-group {
-    margin: 10px 0;
     margin-right: 14px;
     display: inline-block;
     vertical-align: middle;

+ 18 - 2
src/views/indicator/msv/index.vue

@@ -38,12 +38,14 @@
 </template>
 
 <script lang="ts" setup name="IndicatorMsv">
-import { ref, reactive, onUnmounted, shallowRef } from "vue";
+import { ref, reactive, onUnmounted, shallowRef, watch } from "vue";
+import { useRoute } from "vue-router";
 import * as echarts from "echarts";
 import dayjs from "dayjs";
 import Trades from "./components/Trades.vue";
 import { get_indicator } from "@/api";
 
+const route = useRoute();
 const chartRef = ref();
 const tradesRef = ref();
 
@@ -62,7 +64,21 @@ let pageConfig: PageConfig = reactive({
   loading: false,
 });
 
-const pageParams: FormItem = reactive({ symbol: "BTC_USDT", exchange: "gate_usdt_swap", minute_time_range: "240", mills_back: "37" });
+let symbol: any = route.query.symbol?.toString() || "BTC_USDT";
+let exchange: any = route.query.exchange?.toString() || "gate_usdt_swap";
+
+const pageParams: FormItem = reactive({ symbol, exchange, minute_time_range: "240", mills_back: "37" });
+
+watch(
+  route,
+  (value) => {
+    if (value.query.symbol == pageParams.symbol && value.query.exchange == pageParams.exchange) return;
+    pageParams.symbol = value.query.symbol?.toString() || "BTC_USDT";
+    pageParams.exchange = value.query.exchange?.toString() || "gate_usdt_swap";
+    getMsvData();
+  },
+  { deep: true }
+);
 
 let msvChart = shallowRef();
 

+ 239 - 0
src/views/indicator/sybmol_filter/index.vue

@@ -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>

+ 12 - 9
vite.config.ts

@@ -11,13 +11,16 @@ export default defineConfig({
       "@": resolve(__dirname, "./src"),
     },
   },
-  // server: {
-  //   proxy: {
-  //     '/api': {
-  //       target: 'http://cc.skyfffire.com', // 你的目标 API 地址
-  //       changeOrigin: true,
-  //       rewrite: (path) => path.replace(/^\/api/, '/api'),
-  //     },
-  //   },
-  // },
+  server: {
+    host: "0.0.0.0",
+    proxy: {
+      // 代理配置
+      '/api': {
+        target: 'https://4lapi.skyfffire.com', // 目标后端服务地址
+        secure: false,
+        changeOrigin: true, // 必须设置为true
+        rewrite: (path) => path.replace(/^\/api/, '') // 重写请求路径,去掉/api
+      }
+    }
+  },
 });