You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

488 lines
13 KiB

4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
  1. <template>
  2. <view class="main">
  3. <!-- 顶部状态栏占位 -->
  4. <view class="top" :style="{ height: iSMT + 'px' }"></view>
  5. <!-- 标题图标部分 -->
  6. <deepExploration_header
  7. ></deepExploration_header>
  8. <view class="search">
  9. <input
  10. v-model="stockName"
  11. class="searchInput"
  12. type="text"
  13. placeholder="请输入股票名称、股票代码"
  14. placeholder-style="color: #A6A6A6; font-size: 22rpx;"
  15. />
  16. <image
  17. @click="searchStock"
  18. class="seachIcon"
  19. src="/static/deepExploration-images/search.png"
  20. mode="aspectFill"
  21. ></image>
  22. </view>
  23. <!-- 四大功能模块 -->
  24. <view class="select">
  25. <view class="selectItem" @click="toMain('主力追踪')">
  26. <image
  27. class="img"
  28. src="/static/deepExploration-images/icon3.png"
  29. mode="aspectFill"
  30. ></image>
  31. <view class="txt">主力追踪</view>
  32. </view>
  33. <view class="selectItem" @click="toMain('主力雷达')">
  34. <image
  35. class="img"
  36. src="/static/deepExploration-images/icon2.png"
  37. mode="aspectFill"
  38. ></image>
  39. <view class="txt">主力雷达</view>
  40. </view>
  41. <view class="selectItem" @click="toMain('主力解码')">
  42. <image
  43. class="img"
  44. src="/static/deepExploration-images/icon1.png"
  45. mode="aspectFill"
  46. ></image>
  47. <view class="txt">主力解码</view>
  48. </view>
  49. <view class="selectItem" @click="toMain('主力资金流')">
  50. <image
  51. class="img"
  52. src="/static/deepExploration-images/icon4.png"
  53. mode="aspectFill"
  54. ></image>
  55. <view class="txt">主力资金流</view>
  56. </view>
  57. </view>
  58. <!-- 灰色间隔 -->
  59. <view class="gap"></view>
  60. <!-- 选股策略 -->
  61. <view class="stockSelection">
  62. <view class="stockSelection_top">
  63. <view class="txt">
  64. <text>选股策略</text>
  65. </view>
  66. <view class="viewAll" @click="viewAll">
  67. <text>查看全部</text>
  68. </view>
  69. </view>
  70. <view class="stockSelection_content">
  71. <view class="selectionItem">
  72. <view class="header">
  73. <view class="left">
  74. <image
  75. src="/static/deepExploration-images/plus.png"
  76. mode="aspectFill"
  77. ></image>
  78. <text>抄底卖顶</text>
  79. </view>
  80. <view class="right">
  81. <image
  82. src="/static/deepExploration-images/Americle.png"
  83. mode="aspectFill"
  84. ></image>
  85. <text>美股</text>
  86. </view>
  87. </view>
  88. <view class="content">
  89. <view class="contentTitle">
  90. <view class="contentTitle_name">股票名称</view>
  91. <view class="contentTitle_close">最新收盘价</view>
  92. <view class="contentTitle_price">选股价格</view>
  93. </view>
  94. <view class="contentItem">
  95. <view class="row" v-for="(item, index) in stockData" :key="index">
  96. <view class="nameItem">{{ item.tscode }}</view>
  97. <view class="closeItem">{{ item.close }}</view>
  98. <view class="priceItem">{{ item.preClose }}</view>
  99. </view>
  100. </view>
  101. </view>
  102. </view>
  103. </view>
  104. <view class="stockSelection_content">
  105. <view class="selectionItem">
  106. <view class="header">
  107. <view class="left">
  108. <image
  109. src="/static/deepExploration-images/plus.png"
  110. mode="aspectFill"
  111. ></image>
  112. <text>抄底卖顶</text>
  113. </view>
  114. <view class="right">
  115. <image
  116. src="/static/deepExploration-images/Americle.png"
  117. mode="aspectFill"
  118. ></image>
  119. <text>美股</text>
  120. </view>
  121. </view>
  122. <view class="content">
  123. <view class="contentTitle">
  124. <view class="contentTitle_name">股票名称</view>
  125. <view class="contentTitle_close">最新收盘价</view>
  126. <view class="contentTitle_price">选股价格</view>
  127. </view>
  128. <view class="contentItem">
  129. <view class="row" v-for="(item, index) in stockData" :key="index">
  130. <view class="nameItem">{{ item.tscode }}</view>
  131. <view class="closeItem">{{ item.close }}</view>
  132. <view class="priceItem">{{ item.preClose }}</view>
  133. </view>
  134. </view>
  135. </view>
  136. </view>
  137. </view>
  138. </view>
  139. <footerBar class="static-footer" :type="type"></footerBar>
  140. </view>
  141. </template>
  142. <script setup>
  143. import {
  144. ref,
  145. onMounted
  146. } from 'vue'
  147. import footerBar from '@/components/footerBar.vue'
  148. import deepExploration_header from '@/components/deepExploration_header.vue'
  149. import { stocSelectApi } from '@/api/deepExploration/deepExploration.js'
  150. const type = ref("deepExploration");
  151. const iSMT = ref(0);
  152. //查看全部选股策略
  153. const toMain = (val) => {
  154. if (val == "主力追踪") {
  155. uni.navigateTo({
  156. url: "/pages/deepExploration/MainForceActions?index=1",
  157. });
  158. } else if (val == "主力雷达") {
  159. uni.navigateTo({
  160. url: "/pages/deepExploration/MainForceActions?index=2",
  161. });
  162. } else if (val == "主力解码") {
  163. uni.navigateTo({
  164. url: "/pages/deepExploration/MainForceActions?index=3",
  165. });
  166. } else if (val == "主力资金流") {
  167. uni.navigateTo({
  168. url: "/pages/deepExploration/MainForceActions?index=4",
  169. });
  170. }
  171. };
  172. const stockName = ref("");
  173. //搜索股票
  174. const searchStock = () => {
  175. console.log("搜索参数:", stockName.value);
  176. uni.navigateTo({
  177. url: `/pages/deepExploration/MainForceActions?stockName=${stockName.value}`,
  178. });
  179. };
  180. //查看全部选股策略
  181. const viewAll = () => {
  182. uni.navigateTo({
  183. url: '/pages/deepExploration/stockSelectDetail'
  184. })
  185. }
  186. //选股策略数据(接口填充)
  187. const stockData = ref([]);
  188. // 加载选股策略(接口)
  189. const loadStockSelection = async () => {
  190. try {
  191. const res = await stocSelectApi({ language: 'cn', size: 3 })
  192. // console.log('选股策略接口响应原始:', typeof res === 'object' ? JSON.stringify(res) : res)
  193. const raw = res?.data
  194. const listCandidates = [
  195. raw?.list,
  196. raw?.data?.list,
  197. raw?.data?.rows,
  198. raw?.rows,
  199. Array.isArray(raw) ? raw : null
  200. ].filter(Array.isArray)
  201. let list = listCandidates.length ? listCandidates[0] : []
  202. // 若是对象包含多个数组(如不同市场),进行扁平化
  203. if ((!Array.isArray(list) || !list.length) && raw && typeof raw === 'object' && !Array.isArray(raw)) {
  204. const arrays = Object.values(raw).filter(Array.isArray)
  205. if (arrays.length) {
  206. list = arrays.flat()
  207. }
  208. }
  209. if (Array.isArray(list) && list.length) {
  210. const mapped = list.map(item => ({
  211. tscode: item.tsCode ?? item.tscode ?? item.code ?? '',
  212. close: item.close ?? item.lastClose ?? '',
  213. preClose: item.preClose ?? item.preclose ?? item.prevClose ?? ''
  214. }))
  215. stockData.value = mapped.slice(0, 3)
  216. console.log('选股策略列表长度:', stockData.value.length, '首项:', stockData.value[0])
  217. } else {
  218. console.warn('选股策略接口返回空列表或结构不匹配', raw)
  219. }
  220. } catch (e) {
  221. console.error('选股策略接口调用失败', e)
  222. uni.showToast({ title: '选股策略加载失败', icon: 'none' })
  223. }
  224. }
  225. onMounted(() => {
  226. // 状态栏高度
  227. iSMT.value = uni.getSystemInfoSync().statusBarHeight;
  228. // 调用接口填充数据
  229. loadStockSelection()
  230. })
  231. </script>
  232. <style scoped lang="scss">
  233. .main {
  234. width: 100%;
  235. height: 100vh;
  236. background-color: #fff;
  237. .search {
  238. position: relative;
  239. display: flex;
  240. align-items: center;
  241. background-color: #f3f3f3;
  242. width: calc(100% - 60rpx);
  243. height: 80rpx;
  244. border-radius: 50rpx;
  245. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  246. padding: 0 40rpx;
  247. margin: 15rpx 30rpx 0 30rpx;
  248. .seachIcon {
  249. position: absolute;
  250. right: 50rpx;
  251. width: 32rpx;
  252. height: 32rpx;
  253. }
  254. .searchInput {
  255. color: #111;
  256. }
  257. }
  258. .select {
  259. display: flex;
  260. padding: 60rpx 10rpx 30rpx 30rpx;
  261. gap: 70rpx;
  262. align-items: center;
  263. justify-content: center;
  264. .selectItem {
  265. .img {
  266. width: 80rpx;
  267. height: 80rpx;
  268. display: block;
  269. margin: 0 auto;
  270. }
  271. .txt {
  272. color: #6a6a6a;
  273. font-family: "PingFang SC";
  274. font-size: 11px;
  275. font-style: normal;
  276. font-weight: 400;
  277. line-height: 14.5px;
  278. margin-top: 13rpx;
  279. white-space: nowrap;
  280. }
  281. }
  282. }
  283. .gap {
  284. width: 100%;
  285. height: 15rpx;
  286. background-color: #f3f3f3;
  287. }
  288. .stockSelection {
  289. width: 100%;
  290. padding: 32rpx 15rpx;
  291. .stockSelection_top {
  292. display: flex;
  293. justify-content: space-between;
  294. .txt {
  295. color: #000000;
  296. font-family: "PingFang SC";
  297. font-size: 38rpx;
  298. font-style: normal;
  299. font-weight: 400;
  300. line-height: 50rpx;
  301. }
  302. .viewAll {
  303. background-color: #000000;
  304. border-radius: 10rpx;
  305. padding: 6rpx 20rpx;
  306. color: #ffffff;
  307. font-family: "PingFang SC";
  308. font-size: 10rpx;
  309. font-style: normal;
  310. font-weight: 100;
  311. line-height: 29rpx;
  312. height: 40rpx;
  313. }
  314. }
  315. .stockSelection_content {
  316. .selectionItem {
  317. background-color: #f3f3f3;
  318. padding: 30rpx 15rpx 17rpx 30rpx;
  319. border-radius: 30rpx;
  320. margin-top: 30rpx;
  321. .header {
  322. display: flex;
  323. justify-content: space-between;
  324. align-items: center;
  325. .left {
  326. display: flex;
  327. justify-content: space-between;
  328. align-items: center;
  329. image {
  330. display: flex;
  331. justify-content: center;
  332. align-items: center;
  333. width: 15rpx;
  334. height: 15rpx;
  335. }
  336. text {
  337. margin-left: 15rpx;
  338. color: #000000;
  339. font-family: "PingFang SC";
  340. font-size: 28rpx;
  341. font-style: normal;
  342. font-weight: 400;
  343. line-height: 18.5px;
  344. }
  345. }
  346. .right {
  347. display: flex;
  348. justify-content: space-between;
  349. align-items: center;
  350. border-radius: 15rpx;
  351. background-color: #ffffff;
  352. padding: 6rpx 20rpx;
  353. image {
  354. display: flex;
  355. justify-content: center;
  356. align-items: center;
  357. width: 40rpx;
  358. height: 26.5rpx;
  359. }
  360. text {
  361. margin-left: 10rpx;
  362. color: #6a6a6a;
  363. font-family: "PingFang SC";
  364. font-size: 18rpx;
  365. font-style: normal;
  366. font-weight: 400;
  367. line-height: 24rpx;
  368. }
  369. }
  370. }
  371. .content {
  372. .contentTitle {
  373. display: flex;
  374. color: #6a6a6a;
  375. font-family: "PingFang SC";
  376. font-size: 11px;
  377. font-style: normal;
  378. font-weight: 400;
  379. line-height: 14.5px;
  380. margin-top: 24rpx;
  381. margin-bottom: 20rpx;
  382. .contentTitle_name {
  383. width: 100rpx;
  384. }
  385. .contentTitle_close {
  386. width: 130rpx;
  387. margin-left: 260rpx;
  388. }
  389. .contentTitle_price {
  390. width: 120rpx;
  391. margin-left: 60rpx;
  392. }
  393. }
  394. .contentItem {
  395. .row {
  396. display: flex;
  397. box-shadow: 0 -2rpx 5rpx rgba(0, 0, 0, 0.05);
  398. padding: 10rpx 0;
  399. margin-bottom: 10rpx;
  400. .nameItem {
  401. width: 260rpx;
  402. white-space: nowrap;
  403. overflow: hidden;
  404. text-overflow: ellipsis;
  405. color: #000000;
  406. font-family: "PingFang SC";
  407. font-size: 13px;
  408. font-style: normal;
  409. font-weight: 400;
  410. line-height: 17.5px;
  411. }
  412. .closeItem {
  413. width: 120rpx;
  414. margin-left: 100rpx;
  415. color: #25ba5d;
  416. font-family: "PingFang SC";
  417. font-size: 13px;
  418. font-style: normal;
  419. font-weight: 400;
  420. line-height: 17.5px;
  421. }
  422. .priceItem {
  423. width: 120rpx;
  424. margin-left: 73rpx;
  425. color: #25ba5d;
  426. font-family: "PingFang SC";
  427. font-size: 13px;
  428. font-style: normal;
  429. font-weight: 400;
  430. line-height: 17.5px;
  431. }
  432. }
  433. }
  434. }
  435. }
  436. }
  437. }
  438. .static-footer {
  439. position: fixed;
  440. bottom: 0;
  441. }
  442. }
  443. * {
  444. box-sizing: border-box;
  445. }
  446. </style>