From 416079e676643b4e808ce3cc403963d5aba3acf1 Mon Sep 17 00:00:00 2001
From: PC-20250623MANY\Administrator <344137771@qq.com>
Date: Mon, 25 Aug 2025 15:00:27 +0800
Subject: [PATCH] 1

---
 src/components/stock-list.vue |  226 ++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 163 insertions(+), 63 deletions(-)

diff --git a/src/components/stock-list.vue b/src/components/stock-list.vue
index 30656ee..31d7b75 100644
--- a/src/components/stock-list.vue
+++ b/src/components/stock-list.vue
@@ -1,55 +1,73 @@
 <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">
-      <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>
-        </div>
-        <div class="i_name">{{ item.name }}</div>
-      </van-col>
-      <van-col span="4" class="flex-start item_n">{{ item.nowPrice }}</van-col>
-      <van-col span="8" class="item_n">
-        <div class="flex-end" style="margin-bottom: .15em;">
-          {{ item.hcrate }}
-        </div>
-        <div class="flex-end">{{ item.hcrateP }}</div>
-      </van-col>
+    <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">{{
+          item.nowPrice
+        }}</van-col>
 
-      <div class="edit flex-end" v-show="editorShow">
-        <span>{{ $t("移除") }}</span>
-      </div>
-    </van-row>
+        <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>
 
-    <n-pagination
-      :pageNo.sync="pageNum"
-      :pageSize="pageSize"
-      :total="total"
-    ></n-pagination>
+        <div
+          class="edit flex-end"
+          v-show="editorShow"
+          @click.stop="deleteStock(item)"
+        >
+          <span>{{ $t("移除") }}</span>
+        </div>
+      </van-row>
+    </van-list>
+
+    <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 {
-      editorShow: false, // 编辑状态
       pageNum: 1,
-      pageSize: 10,
-      total: 0,
-      stockList: []
+      pageSize: 20,
+      total: 1,
+      stockList: [],
+      loading: false,
+      finished: false
     };
   },
   props: {
@@ -58,78 +76,152 @@
       default: () => {
         return {};
       }
-    }
-  },
-  watch: {
-    propOption: {
-      handler(val) {
-        this.getStockList();
+    },
+    listApi: {
+      default: () => {
+        return api.getStockByType;
       }
     },
-    pageNum: {
-      handler(val) {
-        console.log(val);
-      }
+    // 编辑状态
+    editorShow: {
+      type: Boolean,
+      default: false
     }
   },
+  watch: {},
   mounted() {
-    this.getStockList();
+    this.init();
+    this.initWebSocket();
   },
   methods: {
-    onEdit() {
-      this.editorShow = !this.editorShow;
+    init() {
+      this.pageNum = 1;
+      this.stockList = [];
+      this.getStockList();
     },
+    // 获取数据
     async getStockList() {
-      // 获取数据
       let opt = {
         pageNum: this.pageNum,
         pageSize: this.pageSize,
         stockPlate: "",
         keyWords: "",
-        // stockType: '',
         orderBy: ""
       };
 
       opt = { ...opt, ...this.propOption };
 
-      let data = await api.getStockByType(opt);
-      this.stockList = data.data.list;
-      this.total = data.data.total;
+      let data = await this.listApi(opt);
+      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) {
+      const obj = {
+        pid: item.code || "",
+        type: item.stock_type || ""
+      };
+      window.localStorage.setItem("kLine", JSON.stringify(obj));
+
+      this.$router.push({
+        path: "/kline",
+        query: {
+          code: item.code,
+          type: item.stock_type
+        }
+      });
+    },
+    // 删除自选股
+    async deleteStock(item) {
+      let opt = {
+        code: item.code
+      };
+      let data = await api.delOption(opt);
+      if (data.status === 0) {
+        this.$emit("update:editorShow", false);
+        Toast.success(data.msg);
+        this.getStockList();
+      } else {
+        Toast.fail(data.msg);
+      }
+    },
+    // 连接ws实时监控变动
+    initWebSocket() {
+      console.log("initWebSocket");
+      this.Trade = new WhrWebSocket({
+        path: `wss://usws.yanshiz.com/websocket-server `,
+        onmessage: this.getTradeMessage
+      });
+
+      this.Trade.init();
+    },
+    getTradeMessage({ data }) {
+      let result = JSON.parse(data);
+      let pid = result.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");
     }
   }
 };
 </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;
@@ -147,6 +239,14 @@
       }
     }
 
+    .up {
+      color: @dark_green;
+    }
+
+    .down {
+      color: @red;
+    }
+
     .edit {
       width: 100%;
       height: 100%;

--
Gitblit v1.9.3