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.

462 lines
8.9 KiB

4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
4 weeks ago
  1. <!-- @format -->
  2. <template>
  3. <view class="content">
  4. <!-- 市场子Tab -->
  5. <view class="sub_tabs">
  6. <view v-for="(tab, i) in marketTabs" :key="tab" :class="['tab_item', i === activeTabIndex ? 'active' : '']" @click="switchTab(i)">
  7. <text>{{ tab }}</text>
  8. </view>
  9. </view>
  10. <!-- 大盘指数 -->
  11. <view class="section" v-if="activeTabIndex === 0">
  12. <view class="section_header">
  13. <text class="section_title">大盘指数</text>
  14. <text class="section_action" @click="viewMore('indices')">查看更多 ></text>
  15. </view>
  16. <view class="indices_grid">
  17. <view v-for="(index, i) in countryInfo" :key="i" class="index_item">
  18. <IndexCard :market="index.market" :stockName="index.name" :currentPrice="index.price" :changeAmount="index.change" :changePercent="index.changePercent" :isRising="index.isRising" />
  19. </view>
  20. </view>
  21. <!-- 今日市场情绪温度 -->
  22. <view class="sentiment">
  23. <view class="section_subtitle">
  24. <text>今日市场情绪温度</text>
  25. </view>
  26. <view class="meters">
  27. <view class="meter_item" v-for="(m, i) in sentimentMeters" :key="i">
  28. <image class="meter_icon" :class="m.theme" :src="selectIcons[m.theme]" mode="aspectFit"></image>
  29. <view class="meter_info">
  30. <text class="meter_value" :class="m.theme">{{ m.value }}°C</text>
  31. <text class="meter_label" :class="m.theme">{{ m.label }}</text>
  32. </view>
  33. </view>
  34. </view>
  35. </view>
  36. </view>
  37. <!-- 板块 -->
  38. <view class="section" v-if="activeTabIndex === 1">
  39. <view class="section_header">
  40. <text class="section_title">板块</text>
  41. <text class="section_action" @click="viewMore('sectors')">查看更多 ></text>
  42. </view>
  43. <view class="sectors_grid">
  44. <view v-for="(sec, i) in countryInfo" :key="i" class="sector_item">
  45. <view class="sector_header">
  46. <text class="sector_name">{{ sec.name }}</text>
  47. <text :class="['sector_change', sec.isRising ? 'rising' : 'falling']">
  48. {{ sec.change }}
  49. </text>
  50. </view>
  51. <view class="sector_price">{{ sec.price }}</view>
  52. </view>
  53. </view>
  54. </view>
  55. <!-- 股票 -->
  56. <view class="section" v-if="activeTabIndex === 2">
  57. <view class="section_header">
  58. <text class="section_title">股票</text>
  59. <text class="section_action" @click="viewMore('stocks')">查看更多 ></text>
  60. </view>
  61. <view class="table">
  62. <view class="table_header">
  63. <text class="cell name">名称</text>
  64. <text class="cell price">最新</text>
  65. <text class="cell change">涨幅</text>
  66. </view>
  67. <view class="table_row" v-for="(stk, i) in countryInfo" :key="i">
  68. <view class="cell name">
  69. <text class="stk_name">{{ stk.name }}</text>
  70. <text class="stk_code">{{ stk.code }}</text>
  71. </view>
  72. <view class="cell price">
  73. <text class="stk_price">{{ stk.price }}</text>
  74. </view>
  75. <view class="cell change">
  76. <text :class="['stk_change', stk.isRising ? 'rising' : 'falling']">
  77. {{ stk.change }}
  78. </text>
  79. </view>
  80. </view>
  81. </view>
  82. </view>
  83. <!-- 底部安全区域 -->
  84. <view class="bottom_safe_area"></view>
  85. </view>
  86. </template>
  87. <script setup>
  88. import { ref, computed, onMounted, watch } from "vue";
  89. import IndexCard from "../../components/IndexCard.vue";
  90. import { queryStockDataAPI } from "@/api/marketSituation/marketSituation";
  91. onMounted(() => {
  92. switchTab(0);
  93. });
  94. // 子Tab与操作
  95. // const marketTabs = ["全部", "美股", "纽交所", "纳斯达克"];
  96. const activeTabIndex = ref(0);
  97. const switchTab = (i) => {
  98. activeTabIndex.value = i;
  99. queryStockDataAPI({
  100. parentId: props.countryId,
  101. tradeId: activeTabIndex.value+1,
  102. }).then((res) => {
  103. if (res.code === 200) {
  104. countryInfo.value = res.data.dataPage.records;
  105. console.log(res.data)
  106. console.log(res.data.dataPage.records)
  107. console.log(countryInfo.value);
  108. }
  109. });
  110. };
  111. // 今日情绪温度示例数据
  112. const sentimentMeters = [
  113. { value: 90, label: "道琼斯", theme: "hot" },
  114. { value: 60, label: "纳斯达克", theme: "warm" },
  115. { value: 20, label: "标普500", theme: "cool" },
  116. ];
  117. // 图标映射
  118. const selectIcons = {
  119. hot: "/static/marketSituation-image/hot.png",
  120. warm: "/static/marketSituation-image/warm.png",
  121. cool: "/static/marketSituation-image/cool.png",
  122. };
  123. // Props
  124. const props = defineProps({
  125. countryId: {
  126. type: Number,
  127. required: true,
  128. },
  129. marketTabs: {
  130. type: Array,
  131. },
  132. tabData: {
  133. type: Object,
  134. default: null
  135. },
  136. });
  137. // 计算当前国家信息
  138. const countryInfo = ref('')
  139. // 处理从父组件接收的数据
  140. const handleTabData = (tabData) => {
  141. if (tabData && tabData.type === 'country' && tabData.data) {
  142. if (tabData.data.dataPage && tabData.data.dataPage.records) {
  143. countryInfo.value = tabData.data.dataPage.records;
  144. console.log('countryMarket接收到数据:', countryInfo.value);
  145. }
  146. }
  147. };
  148. // 监听tabData变化
  149. watch(() => props.tabData, (newTabData) => {
  150. if (newTabData) {
  151. handleTabData(newTabData);
  152. }
  153. }, { immediate: true });
  154. // 查看更多占位
  155. const viewMore = (type) => {
  156. // 可根据 type 跳转到相应页面或加载更多
  157. // 例如:indices/sectors/stocks
  158. // uni.navigateTo({ url: `/pages/marketSituation/${type}List` })
  159. };
  160. </script>
  161. <style scoped>
  162. .content {
  163. padding: 0 20rpx 20rpx 20rpx;
  164. }
  165. /* 子Tab */
  166. .sub_tabs {
  167. display: flex;
  168. gap: 16rpx;
  169. padding: 0 20rpx 20rpx 20rpx;
  170. }
  171. .tab_item {
  172. padding: 6rpx 20rpx;
  173. border-radius: 5rpx;
  174. background: #f5f5f5;
  175. color: #666;
  176. font-size: 24rpx;
  177. }
  178. .tab_item.active {
  179. background: #ff4444;
  180. color: #fff;
  181. }
  182. .section {
  183. padding: 20rpx;
  184. border-radius: 16rpx;
  185. }
  186. .section_header {
  187. display: flex;
  188. justify-content: space-between;
  189. align-items: center;
  190. margin-bottom: 16rpx;
  191. }
  192. .section_title {
  193. font-size: 28rpx;
  194. font-weight: bold;
  195. color: #333;
  196. }
  197. .section_action {
  198. font-size: 24rpx;
  199. color: #999;
  200. }
  201. .indices_grid {
  202. display: grid;
  203. grid-template-columns: repeat(3, 1fr);
  204. }
  205. /* 情绪温度 */
  206. .sentiment {
  207. background-color: #f6f6f6;
  208. padding: 0 20rpx 20rpx 20rpx;
  209. }
  210. .section_subtitle {
  211. font-size: 24rpx;
  212. color: #000000;
  213. padding: 20rpx 0;
  214. }
  215. .meters {
  216. display: grid;
  217. grid-template-columns: repeat(3, 1fr);
  218. gap: 16rpx;
  219. }
  220. .meter_item {
  221. display: flex;
  222. align-items: center;
  223. /* padding: 10rpx; */
  224. background: #ffffff;
  225. border-radius: 12rpx;
  226. }
  227. .meter_item image {
  228. width: 100rpx;
  229. height: 100rpx;
  230. }
  231. .meter_info {
  232. display: flex;
  233. flex-direction: column;
  234. }
  235. .meter_value {
  236. font-size: 36rpx;
  237. }
  238. .meter_value.hot {
  239. color: #ff6b6b;
  240. }
  241. .meter_value.warm {
  242. color: #ffd166;
  243. }
  244. .meter_value.cool {
  245. color: #60a5fa;
  246. }
  247. .meter_label {
  248. font-size: 22rpx;
  249. }
  250. .meter_label.hot {
  251. color: #ff6b6b;
  252. }
  253. .meter_label.warm {
  254. color: #ffd166;
  255. }
  256. .meter_label.cool {
  257. color: #60a5fa;
  258. }
  259. /* 板块 */
  260. .sectors_grid {
  261. display: grid;
  262. grid-template-columns: repeat(3, 1fr);
  263. gap: 16rpx;
  264. }
  265. .sector_item {
  266. background: #fafafa;
  267. border-radius: 12rpx;
  268. padding: 16rpx;
  269. }
  270. .sector_header {
  271. display: flex;
  272. justify-content: space-between;
  273. align-items: center;
  274. margin-bottom: 12rpx;
  275. }
  276. .sector_name {
  277. font-size: 24rpx;
  278. color: #333;
  279. }
  280. .sector_change {
  281. font-size: 22rpx;
  282. }
  283. .sector_change.rising {
  284. color: #e74c3c;
  285. }
  286. .sector_change.falling {
  287. color: #27ae60;
  288. }
  289. .sector_price {
  290. font-size: 24rpx;
  291. color: #666;
  292. }
  293. /* 股票表 */
  294. .table {
  295. background: #fff;
  296. border-radius: 12rpx;
  297. overflow: hidden;
  298. }
  299. .table_header,
  300. .table_row {
  301. display: grid;
  302. grid-template-columns: 2fr 1fr 1fr;
  303. padding: 18rpx 20rpx;
  304. border-bottom: 1rpx solid #f0f0f0;
  305. }
  306. .table_header {
  307. background: #fafafa;
  308. }
  309. .cell.name {
  310. display: flex;
  311. flex-direction: column;
  312. }
  313. .stk_name {
  314. font-size: 26rpx;
  315. color: #333;
  316. }
  317. .stk_code {
  318. font-size: 22rpx;
  319. color: #999;
  320. }
  321. .stk_price {
  322. font-size: 26rpx;
  323. color: #333;
  324. }
  325. .stk_change {
  326. font-size: 24rpx;
  327. }
  328. .stk_change.rising {
  329. color: #e74c3c;
  330. }
  331. .stk_change.falling {
  332. color: #27ae60;
  333. }
  334. .index_item {
  335. background: #fff;
  336. border-radius: 12rpx;
  337. overflow: hidden;
  338. }
  339. .hot_stocks {
  340. margin-bottom: 30rpx;
  341. }
  342. .stocks_list {
  343. background: #fff;
  344. border-radius: 12rpx;
  345. overflow: hidden;
  346. }
  347. .stock_item {
  348. display: flex;
  349. justify-content: space-between;
  350. align-items: center;
  351. padding: 24rpx 20rpx;
  352. border-bottom: 1rpx solid #f0f0f0;
  353. }
  354. .stock_item:last-child {
  355. border-bottom: none;
  356. }
  357. .stock_info {
  358. flex: 1;
  359. }
  360. .stock_name {
  361. font-size: 28rpx;
  362. color: #333;
  363. display: block;
  364. margin-bottom: 8rpx;
  365. }
  366. .stock_code {
  367. font-size: 24rpx;
  368. color: #999;
  369. }
  370. .stock_price {
  371. text-align: right;
  372. }
  373. .price {
  374. font-size: 28rpx;
  375. color: #333;
  376. display: block;
  377. margin-bottom: 8rpx;
  378. }
  379. .change {
  380. font-size: 24rpx;
  381. }
  382. .change.rising {
  383. color: #e74c3c;
  384. }
  385. .change.falling {
  386. color: #27ae60;
  387. }
  388. .bottom_safe_area {
  389. height: 120rpx;
  390. }
  391. </style>