10.10综合交易所原始源码-管理后台
1
admin
2026-01-06 089bf5d2378b3c4a61d795b2a92bede2c193b771
src/views/modules/etf-spots/market-linek.vue
New file
@@ -0,0 +1,614 @@
<template>
  <el-dialog
    title="当天分时行情K线设置"
    :close-on-click-modal="false"
    :visible.sync="visible"
    width="1200px"
    @close="handClose"
  >
    <el-form
      :model="dataForm"
      :rules="dataRule"
      ref="dataForm"
      @keyup.enter.native="dataFormSubmit()"
      label-width="120px"
    >
      <el-form-item prop="">
        <div class="green">请先生成K线,才能保存行情配置</div>
      </el-form-item>
      <el-row>
        <el-col :span="7">
          <el-form-item label="开始时间" prop="openTimeTs">
            <el-date-picker
              v-model="dataForm.openTimeTs"
              type="date"
              value-format="yyyy-MM-dd"
              :picker-options="startPickerOptions"
              @change="handleStartTimeChange"
              placeholder="选择日期时间"
            >
            </el-date-picker>
          </el-form-item>
        </el-col>
        <el-col :span="7">
          <el-form-item label="结束时间" prop="closeTimeTs">
            <el-date-picker
              v-model="dataForm.closeTimeTs"
              disabled
              type="date"
              value-format="yyyy-MM-dd"
              :picker-options="endPickerOptions"
              placeholder="选择日期时间"
            >
            </el-date-picker>
          </el-form-item>
        </el-col>
        <el-col :span="5">
          <el-form-item label="交易对" prop="symbol">
            <el-select
              v-model="options.symbol"
              placeholder="请选择"
              @change="changeVal()"
            >
              <el-option
                v-for="item in options"
                :key="item.symbol"
                :label="item.symbol"
                :value="item.symbol"
              >
              </el-option>
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="5">
          <el-form-item label="">
            <el-button type="primary" @click="dataFormSubmitOne()"
              >生成K线</el-button
            >
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="7">
          <el-form-item label="今日开盘价" prop="openPrice">
            <el-input
              v-model="dataForm.openPrice"
              placeholder="今日开盘价"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="7">
          <el-form-item label="今日收盘价" prop="closePrice">
            <el-input
              v-model="dataForm.closePrice"
              placeholder="今日收盘价"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="5">
          <el-form-item label="控盘策略">
            <el-select
              v-model="langug.value"
              placeholder="请选择"
              @change="changeVal()"
            >
              <el-option
                v-for="item in langug"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              >
              </el-option>
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="7">
          <el-form-item label="今日最低价格" prop="low">
            <el-input
              v-model="dataForm.low"
              placeholder="今日最低价格"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="7">
          <el-form-item label="今日最高价格" prop="high">
            <el-input
              v-model="dataForm.high"
              placeholder="今日最高价格"
            ></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="5">
          <el-form-item label="今日总成交量" prop="turnoverLow">
            <el-input
              v-model="dataForm.turnoverLow"
              placeholder="最低"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="1">
          <el-form-item label="" prop="">
            <el-input disabled placeholder="~" class="spann"></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="5">
          <el-form-item label="" prop="turnoverHigh">
            <el-input
              v-model="dataForm.turnoverHigh"
              placeholder="最高"
            ></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <el-form-item label="" prop="">
        <el-button @click="visible = false">取消</el-button>
        <el-button type="primary" v-if="isShow" @click="dataFormSubmit()"
          >保存</el-button
        >
      </el-form-item>
    </el-form>
    <div class="mod-subscribe-general">
      <avue-crud
        ref="crud"
        :page.sync="page"
        :data="dataList"
        :option="tableOption"
        @on-load="getDataList"
      >
        <!-- <template slot="menuLeft">
          <el-button
            type="primary"
            icon="el-icon-plus"
            size="small"
            v-if="isAuth('sys:user:save')"
            @click.stop="addOrUpdateHandle(options)"
            >新增</el-button
          >
        </template> -->
        <template slot-scope="scope" slot="openTimeTss">
          <span>{{ formatTimestamm(scope.row.openTimeTs) }}</span>
        </template>
        <template slot-scope="scope" slot="closeTimeTss">
          <span>{{ formatTimestamm(scope.row.closeTimeTs) }}</span>
        </template>
        <template slot-scope="scope" slot="menu">
          <!-- <el-button
            type="primary"
            icon="el-icon-edit"
            size="small"
            v-if="isAuth('sys:user:delete')"
            @click.stop="addOrUpdateHandle(options,scope.row)"
            >编辑</el-button
          > -->
          <el-button
            type="danger"
            icon="el-icon-delete"
            size="small"
            @click.stop="deleteHandle(scope.row.uuid)"
            >删除</el-button
          >
        </template>
      </avue-crud>
      <!-- 新增删除 -->
      <linKeAdd
        v-if="linKeAddVisible"
        ref="linKeAdd"
        @refreshDataList="getDataList"
      ></linKeAdd>
    </div>
    <echarts ref="addOrUpdate"> </echarts>
    <span slot="footer" class="dialog-footer">
      <el-button @click="visible = false">取消</el-button>
      <el-button type="primary" @click="visible = false">确定</el-button>
    </span>
  </el-dialog>
</template>
<script>
import { tableOption } from "@/crud/etf-spots/market-linek";
import linKeAdd from "./linKen-add-or-undata";
import { treeDataTranslate } from "@/utils";
import { Debounce } from "@/utils/debounce";
import { encrypt } from "@/utils/crypto";
import echarts from "./echats_One.vue";
export default {
  data() {
    return {
      visible: false,
      linKeAddVisible: false,
      menuList: [],
      dateRange: [],
      isShow: false,
      menuListTreeProps: {
        label: "name",
        children: "children",
      },
      startPickerOptions: {
        disabledDate: this.disabledStartDate, // 禁用不满足条件的开始日期
        disabledHours: this.disabledStartHours, // 禁用不满足条件的开始小时
        disabledMinutes: this.disabledStartMinutes, // 禁用不满足条件的开始分钟
        shortcuts: [
          {
            text: "明天",
            onClick: () => {
              const tomorrow = new Date();
              tomorrow.setDate(tomorrow.getDate() + 1);
              tomorrow.setHours(4, 0, 0, 0);
              this.dataForm.openTimeTs = tomorrow;
              this.handleStartTimeChange();
            },
          },
        ],
      },
      endPickerOptions: {
        disabledDate: this.disabledEndDate, // 禁用不满足条件的结束日期
      },
      tableOption: tableOption,
      page: {
        total: 0, // 总页数
        currentPage: 1, // 当前页数
        pageSize: 10, // 每页显示多少条
      },
      dataList: [],
      row: "", //forex->外汇,commodities->大宗商品,指数/ETF->indices, A-stocks->A股, HK-stocks->港股.US-stocks->美股,cryptos->虚拟货币
      options: [],
      linArr: [], //K线数组
      timeArr: [],
      langug: [
        {
          label: "跟随大盘",
          value: "1",
        },
        {
          label: "自定义趋势",
          value: "2",
        },
      ], // 控盘策略
      dataForm: {
        closePrice: "",
        closeTimeTs: "",
        createBy: "",
        createDate: "",
        createTime: "",
        high: "",
        low: "",
        openPrice: "",
        openTimeTs: "",
        robot_model_uuid: "",
        strategy: "",
        symbol: "",
        turnoverHigh: "",
        turnoverLow: "",
        updateBy: "",
        updateDate: "",
        updateTime: "",
        uuid: "",
      },
      dataRule: {
        openTimeTs: [
          { required: true, message: "开始时间不能为空", trigger: "blur" },
        ],
        closeTimeTs: [
          { required: true, message: "结束时间不能为空", trigger: "blur" },
        ],
        openPrice: [
          { required: true, message: "今日开盘价不能为空", trigger: "blur" },
        ],
        closePrice: [
          { required: true, message: "今日收盘价不能为空", trigger: "blur" },
        ],
        low: [
          { required: true, message: "今日最低价不能为空", trigger: "blur" },
        ],
        high: [
          { required: true, message: "今日最高价不能为空", trigger: "blur" },
        ],
        turnoverLow: [
          { required: true, message: "最低不能为空", trigger: "blur" },
        ],
        turnoverHigh: [
          { required: true, message: "最高不能为空", trigger: "blur" },
        ],
        quoteCurrency: [
          { required: true, message: "结算币种不能为空", trigger: "blur" },
        ],
        unitFee: [
          { required: true, message: "手续费不能为空", trigger: "blur" },
        ],
        // sorted: [{ required: true, message: "排序不能为空", trigger: "blur" }],
        // sorted: [{ required: true, message: "排序不能为空", trigger: "blur" }],
        // sorted: [{ required: true, message: "排序不能为空", trigger: "blur" }],
      },
      tempKey: -666666, // 临时key, 用于解决tree半选中状态项不能传给后台接口问题. # 待优化
    };
  },
  components: {
    echarts,
    linKeAdd,
  },
  methods: {
    init(arr) {
      this.options = arr || [];
      this.options.symbol = this.options[0].symbol;
      this.langug.value = this.langug[0].value;
      this.visible = true;
    },
    changeVal(val) {
      this.$forceUpdate();
    },
    addOrUpdateHandle(arr, row) {
      this.linKeAddVisible = true;
      this.$nextTick(() => {
        this.$refs.linKeAdd.init(arr, row);
      });
    },
    disabledStartDate(time) {
      const today = new Date();
      today.setHours(0, 0, 0, 0);
      return time.getTime() <= today.getTime(); // 开始时间只能选择明天及以后的日期
    },
    disabledStartHours() {
      const currentHour = new Date().getHours();
      return Array.from({ length: 24 }, (_, i) => i).filter(
        (hour) => hour < 4 || hour > 21 || (hour === 21 && currentHour >= 30) // 开始时间的小时部分只能选择凌晨4点到晚上21点半
      );
    },
    disabledStartMinutes(hour) {
      const currentHour = new Date().getHours();
      if (hour === 4 && currentHour < 30) {
        // 如果选择的小时是4点且当前小时小于30,则禁用分钟选择
        return Array.from({ length: 60 }, (_, i) => i).filter(
          (minute) => minute !== 0
        );
      } else if (hour === 21 && currentHour >= 30) {
        // 如果选择的小时是21点且当前小时大于等于30,则禁用分钟选择
        return Array.from({ length: 60 }, (_, i) => i).filter(
          (minute) => minute !== 0
        );
      } else {
        // 其他情况不禁用分钟选择
        return [];
      }
    },
    disabledEndDate(time) {
      return true; // 禁用结束时间选择
    },
    handleStartTimeChange() {
      // 设置默认的结束时间为开始时间的后一天
      const startDate = new Date(this.dataForm.openTimeTs);
      const endDate = new Date(startDate.getTime() + 8.64e7); // 一天的毫秒数
      this.dataForm.closeTimeTs = endDate;
    },
    handClose() {
      this.$data.dataForm = JSON.parse(
        JSON.stringify(this.$options.data().dataForm)
      );
      this.$nextTick(() => {
        this.$refs["dataForm"].clearValidate(); // 清除表单验证
      });
      this.langug.value = "";
      this.options.value = "";
      this.isShow = false;
    },
    // 删除
    deleteHandle(id) {
      var ids = id
        ? [id]
        : this.dataListSelections.map((item) => {
            return item.orderId;
          });
      this.$confirm(`确定进行[${id ? "删除" : "批量删除"}]操作?`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          this.$http({
            url: this.$http.adornUrl(`/etf/klineConfig/delete?ids=` + ids),
            method: "delete",
            data: this.$http.adornData(ids, false),
          }).then(({ data }) => {
            this.$message({
              message: "操作成功",
              type: "success",
              duration: 1500,
              onClose: () => {
                this.getDataList(this.page);
              },
            });
          });
        })
        .catch(() => {});
    },
    // 获取数据列表
    getDataList(page, params, done) {
      this.dataListLoading = true;
      this.$http({
        url: this.$http.adornUrl("/etf/klineConfig/pageList"),
        method: "get",
        params: this.$http.adornParams(
          Object.assign(
            {
              type: "indices", //type:'forex', //forex->外汇,commodities->大宗商品,指数/ETF->indices, A-stocks->A股, HK-stocks->港股.US-stocks->美股,cryptos->虚拟货币
              // itemId: this.dataForm.id,
              current: page == null ? this.page.currentPage : page.currentPage,
              size: page == null ? this.page.pageSize : page.pageSize,
            },
            params
          )
        ),
      }).then(({ data }) => {
        if (data.code == 0) {
          console.log("data => " + data);
          this.dataList = data.data.records;
          this.page.total = data.data.total;
        } else {
          this.$message({
            message: data.msg,
            type: "error",
            duration: 1000,
            onClose: () => {},
          });
        }
        this.dataListLoading = false;
        if (done) {
          done();
        }
      });
    },
    formatTimestamp(timestamp) {
      const date = new Date(timestamp);
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, "0");
      const day = String(date.getDate()).padStart(2, "0");
      const hours = String(date.getHours()).padStart(2, "0");
      const minutes = String(date.getMinutes()).padStart(2, "0");
      const seconds = String(date.getSeconds()).padStart(2, "0");
      const milliseconds = String(date.getMilliseconds()).padStart(3, "0");
      const formattedDate = `${year}-${month}-${day} ${hours}:${minutes}:${seconds} ${milliseconds}`;
      return formattedDate;
    },
    formatTimestamm(timestamp) {
      const date = new Date(timestamp);
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, "0");
      const day = String(date.getDate()).padStart(2, "0");
      const hours = String(date.getHours()).padStart(2, "0");
      const minutes = String(date.getMinutes()).padStart(2, "0");
      const seconds = String(date.getSeconds()).padStart(2, "0");
      const milliseconds = String(date.getMilliseconds()).padStart(3, "0");
      const formattedDate = `${year}-${month}-${day}`;
      return formattedDate;
    },
    // K线
    dataFormSubmitOne: Debounce(function () {
      this.$refs["dataForm"].validate((valid) => {
        let a = new Date(this.dataForm.openTimeTs);
        let b = new Date(this.dataForm.closeTimeTs);
        let aa = a.getTime();
        let bb = b.getTime();
        if (valid) {
          this.$http({
            // 生成K线
            url: this.$http.adornUrl(`/etf/klineConfig/init`),
            method: "post",
            data: this.$http.adornData({
              closePrice: this.dataForm.closePrice,
              // closeTimeTs: bb,
              high: this.dataForm.high,
              low: this.dataForm.low,
              openPrice: this.dataForm.openPrice,
              openTimeTs: aa,
              symbol: this.options.symbol,
              turnoverHigh: this.dataForm.turnoverHigh,
              turnoverLow: this.dataForm.turnoverLow,
              strategy: this.langug.value,
              // uuid: ""
            }),
          }).then(({ data }) => {
            if (data.code == 0) {
              this.dataForm.uuid = data.data.modelId;
              this.timeArr = Object.values(
                data.data.klineList.reduce((res, item) => {
                  //res[item.ts] = [item.ts];
                  res[item.ts] = [this.formatTimestamp(item.ts)];
                  return res;
                }, [])
              );
              this.linArr = Object.values(
                data.data.klineList.reduce((res, item) => {
                  let arr = [item.open, item.close, item.low, item.high];
                  res.push(arr);
                  return res;
                }, [])
              );
              this.$nextTick(() => {
                this.$refs.addOrUpdate.init(this.timeArr, this.linArr);
              });
              this.$message({
                message: "操作成功",
                type: "success",
                duration: 1500,
                onClose: () => {},
              });
              this.isShow = true;
            } else {
              this.$message({
                message: data.msg,
                type: "error",
                duration: 1500,
                onClose: () => {},
              });
            }
          });
        }
      });
    }),
    // 表单提交
    dataFormSubmit: Debounce(function () {
      this.$refs["dataForm"].validate((valid) => {
        let a = new Date(this.dataForm.openTimeTs);
        let b = new Date(this.dataForm.closeTimeTs);
        let aa = a.getTime();
        let bb = b.getTime();
        if (valid) {
          this.$http({
            // 修改
            url: this.$http.adornUrl(`/etf/klineConfig/save`),
            method: "post",
            data: this.$http.adornData({
              closePrice: this.dataForm.closePrice,
              // closeTimeTs: bb,
              high: this.dataForm.high,
              low: this.dataForm.low,
              openPrice: this.dataForm.openPrice,
              openTimeTs: aa,
              symbol: this.options.symbol,
              turnoverHigh: this.dataForm.turnoverHigh,
              turnoverLow: this.dataForm.turnoverLow,
              strategy: this.langug.value,
              robot_model_uuid: this.dataForm.uuid,
            }),
          }).then(({ data }) => {
            if (data.code == 0) {
              this.$message({
                message: "操作成功",
                type: "success",
                duration: 1500,
                onClose: () => {
                  this.getDataList();
                  this.$emit("refreshDataList");
                },
              });
            } else {
              this.$message({
                message: data.msg,
                type: "error",
                duration: 1500,
                onClose: () => {},
              });
            }
          });
        }
      });
    }),
  },
};
</script>
<style scoped>
.spann {
  width: 40px;
  margin-left: -60px;
}
</style>