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.

861 lines
23 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
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. <template>
  2. <LoginPrompt ref="loginPrompt"></LoginPrompt>
  3. <view class="main">
  4. <!-- 顶部状态栏占位 -->
  5. <view class="top" :style="{height:iSMT+'px'}"></view>
  6. <deepExploration_header></deepExploration_header>
  7. <view class="search">
  8. <input v-model="searchName" class="searchInput" type="text" placeholder="请输入股票名称、股票代码"
  9. placeholder-style="color: #A6A6A6; font-size: 22rpx;" />
  10. <image @click="searchStock" class="seachIcon" src="/static/deepExploration-images/search.png"
  11. mode="aspectFill"></image>
  12. </view>
  13. <view class="content">
  14. <view class="select">
  15. <image class="img" :src="navItems[currentIndex].icon" mode=""></image>
  16. <view v-for="(item, index) in navItems" :key="index" class="selectItem"
  17. :class="{ active: currentIndex === index }" @click="handleModel(index)">
  18. <button class="btn"></button>
  19. </view>
  20. </view>
  21. <view class="graphAndTxt">
  22. <view class="graph">
  23. <view class="graph_header">
  24. <view class="left">{{stockCode}}</view>
  25. <view class="center">
  26. <text>{{stockName}}</text>
  27. </view>
  28. <view class="right">{{stockTime}}</view>
  29. </view>
  30. <view class="graph_data">
  31. <text>{{stockPrice}}</text>
  32. <text>{{stockChange}}</text>
  33. <text>{{stockAdd}}</text>
  34. </view>
  35. <view class="graph_content">
  36. <view class="charts-box">
  37. <!-- uCharts 蜡烛图组件 -->
  38. <qiun-data-charts type="candle" :opts="opts" :chartData="chartData" :disableScroll="true"
  39. :ontouch="true" :onzoom="true" :key="chartKey" />
  40. </view>
  41. </view>
  42. </view>
  43. <view class="txt">
  44. <view class="txtHeader">
  45. <image src="/static/deepExploration-images/plus.png" mode="aspectFill"></image>
  46. <text>{{navItems[currentIndex].name}}</text>
  47. </view>
  48. <view class="txtContent">
  49. <view v-if="loading" class="loading">加载中...</view>
  50. <rich-text :nodes="htmlContent"></rich-text>
  51. </view>
  52. </view>
  53. </view>
  54. </view>
  55. <!-- 底部切换栏 -->
  56. <footerBar class="static-footer" :type="type"></footerBar>
  57. </view>
  58. </template>
  59. <script setup>
  60. import {
  61. ref,
  62. onMounted,
  63. watch
  64. } from 'vue'
  65. import deepExploration_header from '@/components/deepExploration_header.vue'
  66. import footerBar from '@/components/footerBar.vue'
  67. import {
  68. onLoad
  69. } from '@dcloudio/uni-app'
  70. import {
  71. getModel1First,
  72. getModel1Second,
  73. getModel2First,
  74. getModel2Second,
  75. getModel3First,
  76. getModel3Second,
  77. getModel4First,
  78. getModel4Second,
  79. getModeldefault,
  80. getData
  81. } from '/api/deepExploration/deepExploration.js'
  82. import marked from 'marked'; // 引入 marked 库
  83. import hljs from 'highlight.js';
  84. import 'highlight.js/styles/atom-one-dark.css'; // 可替换为其他主题
  85. import {
  86. useDeepExplorationStore
  87. } from '@/stores/modules/deepExploration'
  88. import {
  89. getUserInfo
  90. } from "@/api/member"
  91. const deepExplorationStore = useDeepExplorationStore()
  92. const historyData = ref({})
  93. // 响应式变量定义
  94. const type = ref('deepExploration')
  95. const iSMT = ref(0)
  96. const currentIndex = ref(0)
  97. const navItems = ref([{
  98. name: '主力追踪',
  99. icon: '/static/deepExploration-images/1.png'
  100. },
  101. {
  102. name: '主力雷达',
  103. icon: '/static/deepExploration-images/2.png'
  104. },
  105. {
  106. name: '主力解码',
  107. icon: '/static/deepExploration-images/3.png'
  108. },
  109. {
  110. name: '主力资金流',
  111. icon: '/static/deepExploration-images/4.png'
  112. },
  113. ])
  114. //搜索股票
  115. const searchStock = () => {
  116. htmlContent.value = ''
  117. console.log('搜索参数:', stockName.value, currentIndex.value);
  118. if (currentIndex.value >= 0 && currentIndex.value <= 3) {
  119. handleModels()
  120. } else {
  121. uni.showToast({
  122. title: '请选择模块',
  123. icon: 'none',
  124. duration: 2000
  125. })
  126. }
  127. }
  128. //点击四大模块
  129. const handleModel = async (index) => {
  130. htmlContent.value = ''
  131. currentIndex.value = index
  132. await handleModels()
  133. // await getServerData()
  134. }
  135. const stockName = ref('Tesla Inc.')
  136. const searchName = ref('')
  137. const stockCode = ref('TSLA')
  138. const language = ref('')
  139. const recordId = ref('')
  140. const parentId = ref('')
  141. const stockId = ref('')
  142. const market = ref('')
  143. const stockTime = ref('2025/10/24')
  144. const loading = ref(true);
  145. const error = ref('');
  146. const htmlContent = ref('');
  147. const markdownContent = ref('');
  148. const renderer = new marked.Renderer();
  149. renderer.heading = function(text, level) {
  150. return `<p>${text}</p>`;
  151. };
  152. // 初始化 marked 配置(支持代码高亮)
  153. marked.setOptions({
  154. highlight: (code, lang) => {
  155. if (lang && hljs.getLanguage(lang)) {
  156. return hljs.highlight(code, {
  157. language: lang
  158. }).value;
  159. }
  160. return hljs.highlightAuto(code).value;
  161. },
  162. renderer,
  163. breaks: true, // 换行转<br>
  164. gfm: true, // 支持GitHub flavored Markdown
  165. sanitize: false, // 保留HTML标签(如<span style>)
  166. });
  167. //获取模型数据
  168. const handleModels = async () => {
  169. try {
  170. // markdownContent.value = '\n## 📊 主力追踪分析:\n\n### 🕵️ 主力行为\n\t1. 📊 该股庄家中长期筹码成本价格为 360.249,短期资金成本价格为 412.577。该股筹码分散,当日筹码成本价格为 444.330。\n\t2. 🔍 近日没有出现主力集中吸筹。\n\t3. 📈 近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。\n\n### 📊 空间维度:\n\t- 📉 预测低一值: <font color=\"#13c2c2\">443.092</font> \n - 📈 预测高一值: <font color=\"#ff4d4f\">466.458</font>\n\t- 📉 预测低二值: <font color=\"#13c2c2\">447.354</font>\n\t- 📈 预测高二值: <font color=\"#ff4d4f\">462.514</font>\n\t<font color=\"#722ed1\">AI智能均线空头排列,当前卖盘小于买盘</font>\n\n### 综合作战\n\t\t\t<font color=\"#fa8c16\">当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线。</font>\n\t\t\t<font color=\"#eb2f96\">该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。</font>\n\n---\n<font color=\"#8c8c8c\">*该内容由AI生成,仅供参考,投资有风险,请注意甄别。*</font>\n '
  171. // htmlContent.value = marked.parse(markdownContent.value);
  172. loading.value = true;
  173. if (searchName.value == '') {
  174. console.log('没有搜索', searchName.value);
  175. handleDefault()
  176. } else {
  177. if (currentIndex.value == 0) {
  178. console.log('搜索', searchName.value);
  179. const result = await getModel1First({
  180. content: searchName.value,
  181. language: "cn",
  182. marketList: "hk,cn,usa,my,sg,vi,in,gb",
  183. model: currentIndex.value + 1
  184. })
  185. console.log('result', result);
  186. if (result.code == 200) {
  187. stockCode.value = result.data.code
  188. // stockName.value = result.data.name
  189. recordId.value = result.data.recordId
  190. parentId.value = result.data.parentId
  191. stockId.value = result.data.stockId
  192. language.value = result.data.language
  193. market.value = result.data.market
  194. const res = await getModel1Second({
  195. language: language.value,
  196. recordId: recordId.value,
  197. parentId: parentId.value,
  198. stockId: stockId.value,
  199. token: 'pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q'
  200. })
  201. if (res.code == 200) {
  202. const rawMarkdown = res.data.markdown;
  203. const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // 全局替换行首的###
  204. markdownContent.value = adaptedMarkdown;
  205. // markdownContent.value = res.data.markdown
  206. htmlContent.value = marked.parse(markdownContent.value);
  207. }
  208. console.log('res', res);
  209. await getServerData()
  210. } else if (result.code == 400) {
  211. markdownContent.value = result.message;
  212. htmlContent.value = marked.parse(markdownContent.value);
  213. } else {
  214. return
  215. }
  216. } else if (currentIndex.value == 1) {
  217. console.log('搜索', searchName.value);
  218. const result = await getModel2First({
  219. content: searchName.value,
  220. language: "cn",
  221. marketList: "hk,cn,usa,my,sg,vi,in,gb",
  222. model: currentIndex.value + 1
  223. })
  224. console.log('result', result);
  225. if (result.code == 200) {
  226. stockCode.value = result.data.code
  227. // stockName.value = result.data.name
  228. recordId.value = result.data.recordId
  229. parentId.value = result.data.parentId
  230. stockId.value = result.data.stockId
  231. language.value = result.data.language
  232. market.value = result.data.market
  233. const res = await getModel2Second({
  234. language: language.value,
  235. recordId: recordId.value,
  236. parentId: parentId.value,
  237. stockId: stockId.value,
  238. token: 'pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q'
  239. })
  240. if (res.code == 200) {
  241. const rawMarkdown = res.data.markdown;
  242. const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // 全局替换行首的###
  243. markdownContent.value = adaptedMarkdown;
  244. // markdownContent.value = res.data.markdown
  245. htmlContent.value = marked.parse(markdownContent.value);
  246. }
  247. console.log('res', res);
  248. await getServerData()
  249. } else if (result.code == 400) {
  250. markdownContent.value = result.message;
  251. htmlContent.value = marked.parse(markdownContent.value);
  252. } else {
  253. return
  254. }
  255. }else if(currentIndex.value == 2){
  256. console.log('搜索', searchName.value);
  257. const result = await getModel3First({
  258. content: searchName.value,
  259. language: "cn",
  260. marketList: "hk,cn,usa,my,sg,vi,in,gb",
  261. model: currentIndex.value + 1
  262. })
  263. console.log('result', result);
  264. if (result.code == 200) {
  265. stockCode.value = result.data.code
  266. // stockName.value = result.data.name
  267. recordId.value = result.data.recordId
  268. parentId.value = result.data.parentId
  269. stockId.value = result.data.stockId
  270. language.value = result.data.language
  271. market.value = result.data.market
  272. const res = await getModel3Second({
  273. language: language.value,
  274. recordId: recordId.value,
  275. parentId: parentId.value,
  276. stockId: stockId.value,
  277. token: 'pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q'
  278. })
  279. if (res.code == 200) {
  280. const rawMarkdown = res.data.markdown;
  281. const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // 全局替换行首的###
  282. markdownContent.value = adaptedMarkdown;
  283. // markdownContent.value = res.data.markdown
  284. htmlContent.value = marked.parse(markdownContent.value);
  285. }
  286. console.log('res', res);
  287. await getServerData()
  288. } else if (result.code == 400) {
  289. markdownContent.value = result.message;
  290. htmlContent.value = marked.parse(markdownContent.value);
  291. } else {
  292. return
  293. }
  294. }else if(currentIndex.value == 3){
  295. console.log('搜索', searchName.value);
  296. const result = await getModel4First({
  297. content: searchName.value,
  298. language: "cn",
  299. marketList: "hk,cn,usa,my,sg,vi,in,gb",
  300. model: currentIndex.value + 1
  301. })
  302. console.log('result', result);
  303. if (result.code == 200) {
  304. stockCode.value = result.data.code
  305. // stockName.value = result.data.name
  306. recordId.value = result.data.recordId
  307. parentId.value = result.data.parentId
  308. stockId.value = result.data.stockId
  309. language.value = result.data.language
  310. market.value = result.data.market
  311. const res = await getModel4Second({
  312. language: language.value,
  313. recordId: recordId.value,
  314. parentId: parentId.value,
  315. stockId: stockId.value,
  316. token: 'pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q'
  317. })
  318. if (res.code == 200) {
  319. const rawMarkdown = res.data.markdown;
  320. const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // 全局替换行首的###
  321. markdownContent.value = adaptedMarkdown;
  322. // markdownContent.value = res.data.markdown
  323. htmlContent.value = marked.parse(markdownContent.value);
  324. }
  325. console.log('res', res);
  326. await getServerData()
  327. } else if (result.code == 400) {
  328. markdownContent.value = result.message;
  329. htmlContent.value = marked.parse(markdownContent.value);
  330. } else {
  331. return
  332. }
  333. }else{
  334. return
  335. }
  336. }
  337. } catch (e) {
  338. error.value = e.message || '加载失败,请重试';
  339. } finally {
  340. loading.value = false;
  341. }
  342. }
  343. const handleDefault = async () => {
  344. const result = await getModeldefault({
  345. token: "pCtw6AYK0EHAaIexoFHsbZjtsfEAIhcmwkCFm6uKko8VPfMvyDiODL9v9c0veic9fIpQbvT8zN4sH/Si6Q",
  346. model: currentIndex.value + 1
  347. })
  348. if (result.code == 200) {
  349. const rawMarkdown = result.data.markdown;
  350. const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // 全局替换行首的###
  351. markdownContent.value = adaptedMarkdown;
  352. htmlContent.value = marked.parse(markdownContent.value);
  353. } else {
  354. }
  355. }
  356. const stockPrice = ref('435.900')
  357. const stockAdd = ref('22.410')
  358. const stockChange = ref('5.120%')
  359. const chartKey = ref(0);
  360. const getServerData = async () => {
  361. const result = await getData({
  362. market: market.value || '',
  363. code: searchName.value || '',
  364. language: "cn",
  365. brainPrivilegeState: 1,
  366. marketList: "usa.sg.my.hk.cn.can.vi.th.in.gb"
  367. })
  368. console.log('k线数据', result);
  369. stockName.value = result.data.StockInformation.Name || 'Tesla Inc.'
  370. stockCode.value = result.data.StockInformation.Code || 'TSLA'
  371. stockTime.value = result.data.StockInformation.Time || '2025/10/29'
  372. stockChange.value = result.data.StockInformation.Zhang || '5.120%'
  373. stockAdd.value = result.data.StockInformation.ZhangFu || '22.410'
  374. stockPrice.value = result.data.StockInformation.Price || '435.900'
  375. if (result.data.chartData) {
  376. chartData.value = {
  377. ...JSON.parse(JSON.stringify(result.data.chartData))
  378. }
  379. chartKey.value++;
  380. console.log('chartData', chartData.value);
  381. }
  382. }
  383. // 1. K线图配置
  384. const opts = ref({
  385. rotate: false,
  386. rotateLock: false,
  387. color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"],
  388. padding: [15, 15, 0, 15],
  389. dataLabel: false,
  390. enableScroll: true,
  391. enableMarkLine: false,
  392. legend: {},
  393. xAxis: {
  394. labelCount: 4,
  395. itemCount: 30,
  396. disableGrid: true,
  397. gridColor: "#CCCCCC",
  398. gridType: "solid",
  399. dashLength: 4,
  400. scrollShow: false,
  401. scrollAlign: "left",
  402. scrollColor: "#A6A6A6",
  403. scrollBackgroundColor: "#EFEBEF",
  404. labelColor: "#8C8C8C",
  405. fontSize: 9
  406. },
  407. yAxis: {
  408. labelColor: "#8C8C8C",
  409. fontSize: 9
  410. },
  411. extra: {
  412. candle: {
  413. color: {
  414. upLine: "#f04864",
  415. upFill: "#f04864",
  416. downLine: "#2fc25b",
  417. downFill: "#2fc25b"
  418. },
  419. average: {
  420. show: false,
  421. name: ["MA5", "MA10", "MA30"],
  422. day: [5, 10, 20],
  423. color: ["#1890ff", "#2fc25b", "#facc14"]
  424. }
  425. },
  426. markLine: {
  427. type: "dash",
  428. dashLength: 5,
  429. data: [{
  430. value: 2150,
  431. lineColor: "#f04864",
  432. showLabel: false
  433. },
  434. {
  435. value: 2350,
  436. lineColor: "#f04864",
  437. showLabel: false
  438. }
  439. ]
  440. },
  441. tooltip: {
  442. showCategory: true
  443. }
  444. }
  445. })
  446. // 2. K线图数据(响应式定义)
  447. const chartData = ref({
  448. categories: [],
  449. series: [{
  450. name: '',
  451. data: []
  452. }]
  453. })
  454. //获取K线数据函数(直接定义,无需methods)
  455. // const getServerData1 = () => {
  456. // // 模拟服务器请求延时
  457. // setTimeout(() => {
  458. // const res = {
  459. // "categories": [
  460. // "2025/10/23",
  461. // "2025/10/24",
  462. // "2025/10/27"
  463. // ],
  464. // series: [{
  465. // "name": "贵州茅台",
  466. // "data": [
  467. // [
  468. // 1455.0,
  469. // 1468.8,
  470. // 1447.2,
  471. // 1467.98
  472. // ],
  473. // [
  474. // 1467.95,
  475. // 1478.88,
  476. // 1449.34,
  477. // 1450.0
  478. // ],
  479. // [
  480. // 1440.0,
  481. // 1452.49,
  482. // 1435.99,
  483. // 1440.41
  484. // ]
  485. // ],
  486. // }]
  487. // }
  488. // // 给响应式变量赋值(需修改.value)
  489. // chartData.value = JSON.parse(JSON.stringify(res))
  490. // }, 500)
  491. // }
  492. let unwatch = null;
  493. // 生命周期钩子:组件挂载后执行(替代onReady)
  494. onMounted(async () => {
  495. iSMT.value = uni.getSystemInfoSync().statusBarHeight
  496. getUserInfo()
  497. await getServerData() // 调用数据获取函数
  498. await handleModels()
  499. unwatch = watch(
  500. () => deepExplorationStore.deepExplorationInfo, // 监听的目标值(函数返回,避免响应式丢失)
  501. (newVal, oldVal) => {
  502. console.log('deepExplorationInfo 变化了:', newVal)
  503. historyData.value = {
  504. ...newVal
  505. }
  506. console.log(historyData.value.wokeFlowData);
  507. console.log('222', historyData.value.stockData.StockInformation);
  508. //工作流数据
  509. const rawMarkdown = historyData.value.wokeFlowData.One.markdown;
  510. const adaptedMarkdown = rawMarkdown.replace(/^### /gm, ''); // 全局替换行首的###
  511. markdownContent.value = adaptedMarkdown;
  512. // markdownContent.value = res.data.markdown
  513. htmlContent.value = marked.parse(markdownContent.value);
  514. //k线
  515. chartData.value = {
  516. ...JSON.parse(JSON.stringify(historyData.value.stockData.chartData))
  517. }
  518. chartKey.value++;
  519. console.log('chartData', chartData.value);
  520. stockName.value = historyData.value.stockData.StockInformation.Name || 'Tesla Inc.'
  521. stockCode.value = historyData.value.stockData.StockInformation.Code || 'TSLA'
  522. stockTime.value = historyData.value.stockData.StockInformation.Time || '2025/10/29'
  523. stockChange.value = historyData.value.stockData.StockInformation.Zhang || '5.120%'
  524. stockAdd.value = historyData.value.stockData.StockInformation.ZhangFu || '22.410'
  525. stockPrice.value = historyData.value.stockData.StockInformation.Price || '435.900'
  526. }, {
  527. deep: true,
  528. immediate: true
  529. } // 开启深度监听(对象内部属性变化也能触发)
  530. )
  531. })
  532. // 页面加载时执行
  533. onLoad((e) => {
  534. if (e.index) {
  535. currentIndex.value = e.index - 1
  536. console.log('模块:', currentIndex.value)
  537. }
  538. if (e.stockName) {
  539. searchName.value = e.stockName
  540. console.log('股票名称:', searchName.value)
  541. }
  542. })
  543. </script>
  544. <style scoped lang="scss">
  545. .main {
  546. width: 100%;
  547. min-height: 100vh;
  548. background-color: #fff;
  549. padding-bottom: 120rpx;
  550. .search {
  551. position: relative;
  552. display: flex;
  553. align-items: center;
  554. background-color: #F3F3F3;
  555. width: calc(100% - 60rpx);
  556. height: 80rpx;
  557. border-radius: 50rpx;
  558. box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
  559. padding: 0 40rpx;
  560. margin: 15rpx 30rpx 0 30rpx;
  561. .seachIcon {
  562. position: absolute;
  563. right: 50rpx;
  564. width: 32rpx;
  565. height: 32rpx;
  566. }
  567. .searchInput {
  568. color: #111;
  569. }
  570. }
  571. .content {
  572. margin-top: 30rpx;
  573. padding-top: 30rpx;
  574. background-color: rgb(248, 248, 248);
  575. .select {
  576. position: relative;
  577. margin-bottom: -5rpx;
  578. .img {
  579. width: 750rpx;
  580. height: 198rpx;
  581. }
  582. .selectItem {
  583. .btn {
  584. position: absolute;
  585. width: 120rpx;
  586. height: 150rpx;
  587. background-color: transparent;
  588. &::after {
  589. border: none;
  590. }
  591. }
  592. &:nth-of-type(1) .btn {
  593. top: 30rpx;
  594. left: 60rpx;
  595. }
  596. &:nth-of-type(2) .btn {
  597. top: 30rpx;
  598. left: 230rpx;
  599. }
  600. &:nth-of-type(3) .btn {
  601. top: 30rpx;
  602. left: 400rpx;
  603. }
  604. &:nth-of-type(4) .btn {
  605. top: 30rpx;
  606. left: 570rpx;
  607. }
  608. }
  609. }
  610. .graphAndTxt {
  611. background-color: #fff;
  612. border-radius: 50rpx 50rpx 0 0;
  613. padding: 68.6rpx 36.5rpx 0 36.5rpx;
  614. .graph {
  615. border: 1rpx solid #e2e2e2;
  616. border-radius: 30rpx 30rpx 0 0;
  617. .graph_header {
  618. padding: 32rpx 20.5rpx 0 24rpx;
  619. display: flex;
  620. align-items: center;
  621. .left {
  622. color: #333333;
  623. font-family: "PingFang SC";
  624. font-size: 15px;
  625. font-style: normal;
  626. font-weight: 400;
  627. line-height: 15px;
  628. }
  629. .center {
  630. margin-left: 155rpx;
  631. display: flex;
  632. align-items: center;
  633. text {
  634. width: 160rpx;
  635. height: 36rpx;
  636. padding-left: 10rpx;
  637. color: #000000;
  638. white-space: nowrap;
  639. overflow: hidden;
  640. text-overflow: ellipsis;
  641. text-align: center;
  642. font-family: "PingFang SC";
  643. font-size: 18px;
  644. font-style: normal;
  645. font-weight: 500;
  646. line-height: 18px;
  647. }
  648. }
  649. .right {
  650. margin-left: 60rpx;
  651. color: #6a6a6a;
  652. font-family: "PingFang SC";
  653. font-size: 13px;
  654. font-style: normal;
  655. font-weight: 400;
  656. line-height: 15px;
  657. }
  658. }
  659. .graph_data {
  660. display: flex;
  661. padding: 48rpx 24rpx;
  662. text {
  663. display: flex;
  664. color: #25ba5d;
  665. font-family: "PingFang SC";
  666. font-size: 17px;
  667. line-height: 17px;
  668. }
  669. text:nth-child(2) {
  670. margin-left: 120rpx;
  671. }
  672. text:nth-child(3) {
  673. margin-left: 150rpx;
  674. }
  675. }
  676. .graph_content {
  677. min-height: 500rpx;
  678. .charts-box {
  679. width: 100%;
  680. height: 100%;
  681. }
  682. }
  683. }
  684. .txt {
  685. background-color: #F3F3F3;
  686. margin-top: 48rpx;
  687. border-radius: 30rpx;
  688. .txtHeader {
  689. padding: 30rpx 24rpx;
  690. image {
  691. width: 20rpx;
  692. height: 20rpx;
  693. }
  694. text {
  695. background-color: #FFFFFF;
  696. color: #000000;
  697. padding: 0 22rpx;
  698. border-radius: 22rpx;
  699. font-size: 28rpx;
  700. font-weight: 400;
  701. line-height: 37rpx;
  702. }
  703. }
  704. .txtContent {
  705. min-height: 200rpx;
  706. padding: 20rpx 30rpx;
  707. margin-bottom: 100rpx;
  708. ::v-deep * {
  709. box-sizing: border-box;
  710. width: 100% !important; // 强制所有解析后的标签占满容器宽度
  711. white-space: normal !important; // 取消强制不换行
  712. word-wrap: break-word !important; // 长词/长数字自动换行
  713. }
  714. // 标题样式(确保换行)
  715. ::v-deep h2 {
  716. font-size: 32rpx;
  717. color: #333;
  718. margin: 25rpx 0 15rpx;
  719. line-height: 1.5;
  720. }
  721. // 段落样式(核心换行控制)
  722. ::v-deep p {
  723. font-size: 26rpx;
  724. color: #666;
  725. margin: 15rpx 0;
  726. line-height: 1.8; // 增加行高,提升可读性
  727. text-align: justify; // 两端对齐,避免单侧参差不齐
  728. }
  729. // 列表样式(纵向排列)
  730. ::v-deep ul,
  731. ::v-deep ol {
  732. margin: 15rpx 0 15rpx 30rpx;
  733. }
  734. ::v-deep li {
  735. margin: 10rpx 0;
  736. line-height: 1.6;
  737. }
  738. // 加载状态样式
  739. .loading {
  740. text-align: center;
  741. padding: 50rpx 0;
  742. color: #666;
  743. font-size: 26rpx;
  744. }
  745. }
  746. }
  747. }
  748. }
  749. .static-footer {
  750. position: fixed;
  751. bottom: 0;
  752. width: 100%;
  753. }
  754. }
  755. * {
  756. box-sizing: border-box;
  757. }
  758. </style>