PC-20250623MANY\Administrator
2025-09-29 58b0f1e9bd03a472321acf1dfc4e89fc4ce9df7a
src/components/stock-list.vue
@@ -1,60 +1,56 @@
<template>
  <div class="stock_list">
  <div class="stock_list flex-center">
    <van-row class="markets_head">
      <van-col span="12" class="flex-start head_item">{{ $t("Name") }}</van-col>
      <van-col span="14" class="flex-start head_item">{{ $t("Name") }}</van-col>
      <van-col span="4" class="flex-start head_item">{{ $t("Price") }}</van-col>
      <van-col span="8" class="flex-end head_item">{{ $t("Change") }}</van-col>
      <van-col span="6" class="flex-end head_item">{{ $t("Change") }}</van-col>
    </van-row>
    <van-row class="markets_item" v-for="item in stockList" :key="item.id" @click="toDetails(item)">
      <van-col span="12" class="item_n">
        <div class="flex-start">
          <span class="i_icon">{{ item.stock_type }}</span>
          <span class="i_hint">{{ item.spell }}</span>
    <van-list v-model="loading" :finished="finished" :finished-text="$t('沒有更多了')" :loading-text="$t('加载中')"
      style="height: 50vh;width: 100%;" @load="onLoad">
      <van-row class="markets_item" v-for="item in stockList" :key="item.id" @click="toDetails(item)">
        <van-col span="14" class="item_n">
          <div class="flex-start">
            <span class="i_icon">{{ item.stock_type }}</span>
            <span class="i_hint">{{ item.spell }}</span>
          </div>
          <div class="i_name">{{ item.name }}</div>
        </van-col>
        <van-col span="4" class="flex-start item_n">
          {{ (Number(item.nowPrice)).toFixed(3) }}
        </van-col>
        <van-col span="6" class="item_n flex-end">
          <div class="flex-end" :class="{ green: item.hcrate < 0, red: item.hcrate > 0 }">
            {{ item.hcrateP }}
          </div>
        </van-col>
        <div class="edit flex-end" v-show="editorShow" @click.stop="deleteStock(item)">
          <span>{{ $t("移除") }}</span>
        </div>
        <div class="i_name">{{ item.name }}</div>
      </van-col>
      <van-col span="4" class="flex-start item_n">{{ item.nowPrice }}</van-col>
      </van-row>
    </van-list>
      <van-col span="8" class="item_n">
        <div class="flex-end" style="margin-bottom: .15em;" :class="{ red: item.hcrate < 0, green: item.hcrate > 0 }">
          {{ item.hcrate }}
        </div>
        <div class="flex-end" :class="{ red: item.hcrate < 0, green: item.hcrate > 0 }">
          {{ item.hcrateP }}
        </div>
      </van-col>
      <div class="edit flex-end" v-show="editorShow" @click.stop="deleteStock(item)">
        <span>{{ $t("移除") }}</span>
      </div>
    </van-row>
    <!-- 无数据时显示 -->
    <div class="no_data flex-center" v-show="!stockList || stockList.length == 0">
      <img src="@/assets/img/zhaobudao2.png" alt="" />
    </div>
    <n-pagination :pageNo.sync="pageNum" :pageSize="pageSize" :total="total"></n-pagination>
    <van-skeleton :row="7" v-if="stockList.length == 0" style="margin-top: 1em;" />
  </div>
</template>
<script>
import nPagination from "@/components/nPagination.vue";
import * as api from "@/axios/api";
import { Toast } from "vant";
import { WhrWebSocket } from "@/utils/WhrWebSocket";
export default {
  name: "stock_list",
  components: {
    nPagination
  },
  components: {},
  data() {
    return {
      pageNum: 1,
      pageSize: 10,
      pageSize: 20,
      total: 1,
      stockList: []
      stockList: [],
      loading: false,
      finished: false
    };
  },
  props: {
@@ -75,25 +71,17 @@
      default: false
    }
  },
  watch: {
    propOption: {
      handler(val) {
        this.pageNum = 1;
        this.getStockList();
      }
    },
    pageNum: {
      handler(val) {
        // this.stockList = [];
        this.getStockList();
      }
    }
  },
  watch: {},
  mounted() {
    this.getStockList();
    this.init();
    this.initWebSocket();
  },
  methods: {
    init() {
      this.pageNum = 1;
      this.stockList = [];
      this.getStockList();
    },
    // 获取数据
    async getStockList() {
      let opt = {
@@ -101,15 +89,22 @@
        pageSize: this.pageSize,
        stockPlate: "",
        keyWords: "",
        // stockType: '',
        orderBy: ""
      };
      opt = { ...opt, ...this.propOption };
      let data = await this.listApi(opt);
      this.stockList = data.data.list;
      this.total = data.data.total || 1;
      if (data.status == 0) {
        this.stockList = [...this.stockList, ...data.data.list];
        // this.total = data.data.total || 1;
        // 加载状态结束
        this.loading = false;
        if (data.data.list.length <= 0) {
          this.finished = true;
        }
      }
    },
    // 点击进入详情
    toDetails(item) {
@@ -145,8 +140,8 @@
    initWebSocket() {
      console.log("initWebSocket");
      this.Trade = new WhrWebSocket({
        path: `wss://ws.kuspitai.com/websocket-server `,
        onmessage: this.getTradeMessage,
        path: `wss://usws.yanshiz.com/websocket-server `,
        onmessage: this.getTradeMessage
      });
      this.Trade.init();
@@ -154,53 +149,65 @@
    getTradeMessage({ data }) {
      let result = JSON.parse(data);
      let pid = result.pid;
      let userToUpdate = this.stockList.find((item) => item.code == pid);
      let userToUpdate = this.stockList.find(item => item.code == pid);
      if (userToUpdate) {
        // 更新对象数据
        userToUpdate.nowPrice = result.last;
        userToUpdate.hcrateP = result.pcp;
      }
    },
    onLoad() {
      console.log("dddddddd");
      this.pageNum++;
      this.getStockList();
    }
  },
  beforeDestroy() {
    if (this.Trade) {
      this.Trade.close();
      console.log('WebSocket disconnected');
      console.log("WebSocket disconnected");
    }
  },
  }
};
</script>
<style lang="less" scoped>
<style lang="less">
@green2: #f0f0f0;
@dark_green: #07c160;
@red: #ee0a24;
#app {
  padding-bottom: 1.4rem;
}
.stock_list {
  flex-direction: column;
  .markets_head {
    background-color: @green2;
    // background-color: @green2;
    margin-top: 0.25em;
    height: 1em;
    width: 100%;
    padding: 0 0.25em;
    .head_item {
      font-size: 0.4em;
      font-size: 0.3em;
      height: 100%;
      font-weight: 600;
      font-weight: 300;
      color: #898a8e;
    }
  }
  .markets_item {
    // margin-top: .25em;
    // height: 1em;
    padding: 0.5em 0.25em 0.25em;
    border-bottom: #f5f5f5 solid 0.01em;
    border-bottom: rgba(#fff, 0.2) solid 0.01em;
    position: relative;
    .item_n {
      font-size: 0.4em;
      font-size: 0.3em;
      min-height: 2em;
      font-weight: 500;
      font-weight: 300;
      .i_icon {
        border-radius: 0 26em 26em 0;