Compare commits

...

94 Commits

Author SHA1 Message Date
wangyetao d4805e71df 空白 4 weeks ago
wangyetao 67e38ed6c7 Merge branch 'dongqian/feature-20251022181325-deepmate简版' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into wangyi/feature-20251022162725-启动页登录注册 4 weeks ago
Ethereal 309bb64c6c 优化找回密码页面验证逻辑 4 weeks ago
wangyetao 30de1a500e 优化历史记录滑动 4 weeks ago
wangyetao 63f8144af0 优化历史结构 4 weeks ago
Ethereal ae4799e702 优化deepmate滚动动画 4 weeks ago
Ethereal a3edcce138 优化登录注册的验证逻辑 4 weeks ago
Ethereal 09e7053323 注册页优化服务协议 4 weeks ago
Ethereal a218a53a15 优化服务协议弹窗 4 weeks ago
wangyetao c5ec095ebe 安装pinia 4 weeks ago
wangyetao 6af246bf65 Merge branch 'wangyi/feature-20251022162725-启动页登录注册' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into dongqian/feature-20251022181325-deepmate简版 4 weeks ago
Ethereal 3e640ea898 deepmate改成设计稿样式 4 weeks ago
Ethereal 88e76be174 合并分支0 4 weeks ago
wangyetao 253e01c5cb 合并代码 4 weeks ago
Ethereal 928f7d8711 合并代码 4 weeks ago
Ethereal e060eaca16 Merge branch 'dongqian/feature-20251022181325-deepmate简版' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into wangyi/feature-20251022162725-启动页登录注册 4 weeks ago
Ethereal 2ec6045bb2 添加login接口 4 weeks ago
Ethereal ef2ff18aa9 添加deepmate请求接口 4 weeks ago
Ethereal 4a9e5ab920 封装http请求 4 weeks ago
Ethereal eb18cf3c45 优化deepmate思考过程样式 4 weeks ago
wangyetao 47281ef48f Merge branch 'wangyi/feature-20251022162725-启动页登录注册' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into dongqian/feature-20251022181325-deepmate简版 4 weeks ago
Ethereal 8dded599c8 优化聊天区域滑动范围 4 weeks ago
wangyetao 6fc67da169 Merge branch 'wangyi/feature-20251022162725-启动页登录注册' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into dongqian/feature-20251022181325-deepmate简版 4 weeks ago
wangyetao 864045d7ae 合并代码 4 weeks ago
Ethereal 6885560fee 合并董倩代码 4 weeks ago
Ethereal 42603a03a9 优化deepmate 4 weeks ago
wangyetao 6eed33e9c2 增加历史记录 4 weeks ago
Ethereal 9418e86122 重新优化选择页样式 4 weeks ago
Ethereal 15e7bdce90 优化选择页滑动逻辑 4 weeks ago
wangyetao f4f5514df0 优化 4 weeks ago
Ethereal 1571a304ba 完成找回密码逻辑 4 weeks ago
Ethereal 60a21662d3 输入框增添隐藏图表 4 weeks ago
Ethereal 422de331d9 增添找回密码页面 4 weeks ago
Ethereal c3d7906515 增添邮箱验证规则 4 weeks ago
Ethereal 75fc4aaa60 增添手机号验证规则 4 weeks ago
wangyetao 36e554ab44 修复合并之后的代码 4 weeks ago
Ethereal 7ea9cd6ac4 Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into wangyi/feature-20251022162725-启动页登录注册 4 weeks ago
Ethereal dc7cc6f5c3 添加未勾选用户协议弹窗 4 weeks ago
Ethereal 7908314c32 优化思考过程,增添时间用时0 4 weeks ago
Ethereal f954ec4130 优化思考过程,增添时间用时 4 weeks ago
zhaowenkang b749ebe11b api文件夹 1 month ago
Ethereal 80380db0a8 开发请求接口0 1 month ago
wangyetao 437597a706 完善聊天页面的功能 1 month ago
Ethereal 170adc5bf1 优化思考过程代码 1 month ago
zhaowenkang a9662a0af8 自定义请求头 1 month ago
Ethereal 94682e1e24 注册markdown格式 1 month ago
zhaowenkang dee827ecb7 封装请求,行情页面完善 1 month ago
宋杰 32314d9a98 Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 1 month ago
宋杰 fb2d06a25a 首页deepMate输入框将用户输入内容发送到深度探索页面; 1 month ago
宋杰 f9c893bd90 Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 1 month ago
宋杰 d297bd32dd 首页deepmate部分默认展示3条数据; 1 month ago
宋杰 757ec0ec68 Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 1 month ago
宋杰 1d8de7df7c 首页的深度探索右侧查看更多点击后跳转深度探索页面; 1 month ago
宋杰 03c995fe41 Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 1 month ago
宋杰 305c8327bb deepMate的logo加入波纹动效。 1 month ago
Ethereal 3e23bcc130 优化滚动效果 1 month ago
Ethereal de93dcda75 添加文字滚动效果 1 month ago
Ethereal c9335705ed 优化打字机样式 1 month ago
wangyetao 78ac48ad64 聊天框上方保留机器人 1 month ago
宋杰 9c4744c957 Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 1 month ago
宋杰 cf375ab7ae 首页我的自选加入免责声明; 1 month ago
宋杰 09b6d61aad Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 1 month ago
宋杰 0b671bc3f6 为添加自选股添加点击事件,跳转到行情页。 1 month ago
wangyetao 87f4c41515 调整卡片样式 1 month ago
wangyetao 719ff43193 增加导入footerbar 1 month ago
wangyetao 52add52df0 Merge branch 'wangyi/feature-20251022162725-启动页登录注册' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into dongqian/feature-20251022181325-deepmate简版 1 month ago
wangyetao 37b3f53bf2 调整一下页面 1 month ago
宋杰 a73f499c4e Merge branch 'songjie/feature-20251023161635-首页' into milestone-20251031-简版功能开发 1 month ago
Ethereal 8c78b39294 优化DeepMate样式 1 month ago
宋杰 8acce471b5 新建早盘解析页面并跳转成功; 1 month ago
zhaowenkang fcb9eeac98 动态计算遮挡和地图尺寸 1 month ago
wangyetao 2a2a772462 增加词条滚动功能 1 month ago
Ethereal b678f207e8 注册tab组件到登录页 1 month ago
wangyetao 83c0f2eaaf 缺省页 1 month ago
zhaowenkang d6cd8fbc55 行情页面搭建 1 month ago
Ethereal 659968b678 Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into wangyi/feature-20251022162725-启动页登录注册 1 month ago
Ethereal 82d3361d04 Merge branch 'dongqian/feature-20251022181325-deepmate简版' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into wangyi/feature-20251022162725-启动页登录注册 1 month ago
wangyetao dbdd5d4229 修复 1 month ago
wangyetao 53d84192e0 修复完善deepmate页面 1 month ago
Ethereal 04c80b494d 完成登录注册页面布局 1 month ago
Ethereal 216e8a469e 完成登录界面 1 month ago
宋杰 97c39e1020 home页的耳机和铃铛图标换成图片; 1 month ago
宋杰 092b781ef4 首页样式完成。 1 month ago
宋杰 1aee77cf79 今日市场概览的logo垂直居中; 1 month ago
宋杰 62774fc1fd 首页框架 1 month ago
Ethereal 4bd1fd5198 修改未登录提示信息 1 month ago
Ethereal 1fde0e423c 增添手机验证码登录 1 month ago
Ethereal 0781fb1dd6 修改登录界面样式 1 month ago
wangyetao 0cd4dd619a 修改ui图标 1 month ago
Ethereal 14753b4af7 手机号增添不同国家的区号全 1 month ago
Ethereal 0232b2bac8 手机号增添不同国家的区号 1 month ago
Ethereal c9357ba44d 备份main 1 month ago
Ethereal 5cb7fa6101 优化配置 1 month ago
Ethereal 046e80e6d8 启动页初始化 1 month ago
  1. 9
      .hbuilderx/launch.json
  2. 90
      api/deepMate/deepMate.js
  3. 105
      api/start/login.js
  4. 198
      components/DeepMate.vue
  5. 385
      components/MarketOverview.vue
  6. 192
      components/footerBar-cn.vue
  7. 2
      components/footerBar.vue
  8. 159
      components/login-prompt.vue
  9. 110
      main.js
  10. 116
      main.js.bgk
  11. 13
      manifest.json
  12. 857
      package-lock.json
  13. 12
      package.json
  14. 119
      pages.json
  15. 23
      pages/blank/blank.vue
  16. 1524
      pages/deepMate/deepMate.vue
  17. 63
      pages/deepMate/scroll/scroll.vue
  18. 699
      pages/home/home.vue
  19. 949
      pages/start/Registration/Registration.vue
  20. 1341
      pages/start/Registration/list.js
  21. 13
      pages/start/agreement/agreement.vue
  22. 55
      pages/start/index/index.vue
  23. 1341
      pages/start/login/list.js
  24. 1111
      pages/start/login/login.vue
  25. 69
      pages/start/login/verification.js
  26. 13
      pages/start/privacy/privacy.vue
  27. 976
      pages/start/recoverPassword/recoverPassword.vue
  28. 175
      pages/start/select/select.vue
  29. 56
      pages/start/startup/startup.vue
  30. 23
      server/deepchart.json
  31. 131
      server/login.json
  32. BIN
      static/flag/ad.png
  33. BIN
      static/flag/ae.png
  34. BIN
      static/flag/af.png
  35. BIN
      static/flag/ag.png
  36. BIN
      static/flag/ai.png
  37. BIN
      static/flag/al.png
  38. BIN
      static/flag/am.png
  39. BIN
      static/flag/an.png
  40. BIN
      static/flag/ao.png
  41. BIN
      static/flag/aq.png
  42. BIN
      static/flag/ar.png
  43. BIN
      static/flag/as.png
  44. BIN
      static/flag/at.png
  45. BIN
      static/flag/au.png
  46. BIN
      static/flag/aw.png
  47. BIN
      static/flag/ax.png
  48. BIN
      static/flag/az.png
  49. BIN
      static/flag/ba.png
  50. BIN
      static/flag/bb.png
  51. BIN
      static/flag/bd.png
  52. BIN
      static/flag/be.png
  53. BIN
      static/flag/bf.png
  54. BIN
      static/flag/bg.png
  55. BIN
      static/flag/bh.png
  56. BIN
      static/flag/bi.png
  57. BIN
      static/flag/bj.png
  58. BIN
      static/flag/bl.png
  59. BIN
      static/flag/bm.png
  60. BIN
      static/flag/bn.png
  61. BIN
      static/flag/bo.png
  62. BIN
      static/flag/bq.png
  63. BIN
      static/flag/br.png
  64. BIN
      static/flag/bs.png
  65. BIN
      static/flag/bt.png
  66. BIN
      static/flag/bv.png
  67. BIN
      static/flag/bw.png
  68. BIN
      static/flag/by.png
  69. BIN
      static/flag/bz.png
  70. BIN
      static/flag/ca.png
  71. BIN
      static/flag/cc.png
  72. BIN
      static/flag/cd.png
  73. BIN
      static/flag/cf.png
  74. BIN
      static/flag/cg.png
  75. BIN
      static/flag/ch.png
  76. BIN
      static/flag/ci.png
  77. BIN
      static/flag/ck.png
  78. BIN
      static/flag/cl.png
  79. BIN
      static/flag/cm.png
  80. BIN
      static/flag/cn.png
  81. BIN
      static/flag/co.png
  82. BIN
      static/flag/cr.png
  83. BIN
      static/flag/cu.png
  84. BIN
      static/flag/cv.png
  85. BIN
      static/flag/cw.png
  86. BIN
      static/flag/cx.png
  87. BIN
      static/flag/cy.png
  88. BIN
      static/flag/cz.png
  89. BIN
      static/flag/de.png
  90. BIN
      static/flag/dj.png
  91. BIN
      static/flag/dk.png
  92. BIN
      static/flag/dm.png
  93. BIN
      static/flag/do.png
  94. BIN
      static/flag/dz.png
  95. BIN
      static/flag/ec.png
  96. BIN
      static/flag/ee.png
  97. BIN
      static/flag/eg.png
  98. BIN
      static/flag/eh.png
  99. BIN
      static/flag/er.png
  100. BIN
      static/flag/es.png

9
.hbuilderx/launch.json

@ -0,0 +1,9 @@
{
"version" : "1.0",
"configurations" : [
{
"playground" : "standard",
"type" : "uni-app:app-ios"
}
]
}

90
api/deepMate/deepMate.js

@ -0,0 +1,90 @@
import { http } from '../../utils/http'
export const getData = () => {
return http({
method: 'GET',
url: '/ka',
})
}
/**
* 意图识别
{
"content":"森那美",
"language": "cn",
"marketlist": "hk,cn,usa,my,sg,vi,in,gb",
"token": "9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnilrmTwo5Fb"qJ91WrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs"
"model":1
}
* {
"code": 200,
"message": "操作成功",
"data": {
"code": "1A0001",
"market": "cn",
"name": "上证指数",
"refuse": "",
"recordId": 15,
"parentId": 14,
"stockId": 25,
"language": "cn",
"debug_url": "https://www.coze.cn/work_flow?execute_id=7564771475955515444&space_id=7564250621483040822&workflow_id=7564368306322292788&execute_mode=2"
}
*/
export const postIntent = (data) => {
return http({
method: 'GET',
url: '/intent',
data
})
}
/**
* 获取股票信息
* data{
"language": "cn",
"token": "9ior41AF0xTIbIG2pRnnbZi0+fEeMx8pywnIlrmTwo5FbqJ9lWrSWOxp9MkpKiNtedtUafqvzIwpFKrwuMs",
"recordId": 5214,
"parentId": 4887,
"stockId": 1523
}
*
{"cftl":"当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线","date":"更新时间: 24/10/2025","debug_url":"https://www.coze.cn/work_flow?execute_id=7565080703726846004&space_id=7564250621483040822&workflow_id=7564596757864071195&execute_mode=2","gfzl":"该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。","hxjzpg":"(1)牛股评级:★★☆☆☆\n(2)暴涨概率:40%\n(3)风险评估:非常安全\n(4)黄金价域:258.984~266.753\n(5)核心证据链\n 资金共识:当日多方资金流入\n 趋势动能:该股中长期处于上升趋势,短期处于强势状态。","kongjian":"预测低一值255.468,预测高一值257.692,预测低二值255.156,预测高二值255.807",
"markdown":"\n# <font color=\"#1890ff\">Alphabet Inc.全景作战报告</font>\n## 📊 股票分析报告\n### 📈 股票基本信息\n- **股票名称**: <font color=\"#52c41a\">Alphabet Inc.</font>\n- **股票代码**: <font color=\"#1890ff\">GOOGL</font>\n- **当前价格**: <font color=\"#ff4d4f\">259.920</font>\n- **更新时间**: 2025年10月24日\n- **时间节点**: 今日无变盘点\n\n### 🎯 核心价值评估\n- **安全边际**: <font color=\"#13c2c2\">164.424 ~ </font>\n- **黄金价域**: <font color=\"#faad14\">258.984 ~ 266.753</font>\n- **核心证据链**:\n - 🟢 **资金共识**: 当日多方资金<font color=\"#52c41a\">流入</font>\n - 🔥 **趋势动能**: 该股中长期处于<b><font color='#FF0000'>上升趋势</font></b>,短期处于<b><font color='#FF0000'>强势状态</font></b>。\n\n### 🕵️ 主力作战分析\n- **主力行为**:\n 1. 📊 该股庄家中长期筹码成本价格为 207.497,短期资金成本价格为 239.503。该股筹码分散,当日筹码成本价格为 254.335。\n 2. 🔍 近日没有出现主力集中吸筹。\n 3. 📈 近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。\n\n### 📊 技术分析\n- **空间维度**:\n - 📉 预测低一值: <font color=\"#13c2c2\">255.468</font>\n - 📈 预测高一值: <font color=\"#ff4d4f\">257.692</font>\n - 📉 预测低二值: <font color=\"#13c2c2\">255.156</font>\n - 📈 预测高二值: <font color=\"#ff4d4f\">255.807</font>\n- **能量分析**: <font color=\"#722ed1\">AI智能均线多头排列,当前卖盘小于买盘</font>\n\n### ⚡ 综合作战分析\n- **触发条件**: <font color=\"#fa8c16\">当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线</font>\n- **攻防指令**: <font color=\"#eb2f96\">该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。</font>\n\n---\n<font color=\"#8c8c8c\">*该内容由AI生成,仅供参考,投资有风险,请注意甄别。*</font>\n ","message":"","name":"股票名称: Alphabet Inc.(GOOGL)","nengliang":"AI智能均线多头排列,当前卖盘小于买盘","price":"当前价格: 259.920","shijian":"今日无变盘点","zhuli1":"(1)该股庄家中长期筹码成本价格为 207.497,短期资金成本价格为 239.503。该股筹码分散,当日筹码成本价格为 254.335。","zhuli2":"(2)近日没有出现主力集中吸筹。","zhuli3":"(3)近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。"}
}
*/
export const postStock = (data) => {
return http({
method: 'GET',
url: '/stocks',
data
})
}
/**
* 获取历史记录
*/
export const postHistory = (data) => {
return http({
method: 'POST',
url: '/history',
data
})
}
/**
*
*/

105
api/start/login.js

@ -0,0 +1,105 @@
import { http } from '../../utils/http'
/**
*
* @param data 模拟手机号码
* {
"loginType":"EMAIL", //登录方式
"account":"q614588746@163.com" , //登陆账号 手机号/邮箱/dccode
"verifyCode":"837012", //验证码
"password":"", //密码
"useCode":"true", //是否使用验证码 true/false
"idToken":"", //第三方登录idToken
}
*/
export const LoginApi = (data) => {
return http({
method: 'GET',
url: '/loginFailureWrongCode',
data: {
data
},
})
}
/**
* 发送验证码
* @param {*} phoneNumber
* @returns
*/
export const SendCodeApi = (data) => {
return http({
method: 'GET',
url: '/sendCodeFailureTooFrequent',
data:{
data
}
})
}
/**
* 注册
*/
export const register = (data) => {
return http({
method: 'GET',
url: '/register',
data: {
data
},
})
}
/**
* 修改密码
*
*/
export const updatePassword = (data) => {
return http({
method: 'GET',
url: '/updatePassword',
data: {
data
},
})
}
/**
* 通过苹果登录
*/
export const postLoginAppleSimpleAPI = (phoneNumber) => {
return http({
method: 'POST',
url: '/login',
data: {
phoneNumber,
},
})
}
/**
* 通过谷歌登录
*/
export const postLoginGoogleSimpleAPI = (phoneNumber) => {
return http({
method: 'POST',
url: '/login/wxMin/simple',
data: {
phoneNumber,
},
})
}

198
components/DeepMate.vue

@ -0,0 +1,198 @@
<template>
<view class="deepmate">
<view class="deepmate-container">
<view class="deepmate-header">
<view class="title-container">
<view class="title-left">
<text class="deepmate-title">DeepMate</text>
<text class="deepmate-subtitle">您的市场最佳顾问~</text>
</view>
<view class="title-right">
<image class="deepmate-icon" src="https://d31zlh4on95l9h.cloudfront.net/images/7faa683450cc071bcc746fea8191ff6b.png" mode="aspectFit"></image>
</view>
</view>
</view>
<view class="deepmate-content">
<view class="deepmate-hotspots">
<view class="deepmate-question">
<text class="question-text">今日股票策略晨报</text>
</view>
<view class="hotspot-item">
<text>热门股票分析</text>
</view>
<view class="hotspot-item">
<text>行业趋势预测</text>
</view>
<view class="hotspot-item">
<text>市场风险提示</text>
</view>
<view class="hotspot-item">
<text>投资策略建议</text>
</view>
<view class="hotspot-item">
<text>财经新闻解读</text>
</view>
</view>
<view class="deepmate-action">
<input class="stock-input" type="text" placeholder="请输入股票代码/名称,获取AI洞察" />
<view class="send-button-container">
<image class="send-button" src="https://d31zlh4on95l9h.cloudfront.net/images/3da018821a5c82b06a1d6ddc81b960ac.png" mode="aspectFit"></image>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
name: 'DeepMate',
data() {
return {
}
}
}
</script>
<style>
/* DeepMate样式 */
.deepmate-container {
background-color: #ffe6e6;
border-radius: 10px;
padding: 15px 15px 15px 15px;
margin: 0;
width: 100%;
box-sizing: border-box;
overflow: hidden;
}
.deepmate-header {
margin-bottom: 10px;
}
.title-container {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.title-left {
width: 50%;
display: flex;
flex-direction: column;
}
.title-right {
width: 50%;
display: flex;
justify-content: center;
align-items: center;
}
.deepmate-title {
font-size: 18px;
font-weight: bold;
color: #ff4d4f;
display: block;
}
.deepmate-icon {
width: 50px;
height: 50px;
margin-left: 0;
}
.deepmate-subtitle {
font-size: 12px;
color: #666;
display: block;
margin-top: 5px;
}
.deepmate-hotspots {
margin: 10px 0;
background-color: #ffffff;
border-radius: 10px;
padding: 10px;
}
.deepmate-question {
display: flex;
align-items: center;
margin-bottom: 10px;
padding-left: 10px;
position: relative;
}
.deepmate-question:before {
content: "";
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4px;
background-color: #ff4d4f;
border-radius: 2px;
}
.question-text {
font-size: 16px;
font-weight: bold;
color: #333;
}
.hotspot-item {
background-color: #f5f5f5;
padding: 8px 12px;
border-radius: 6px;
margin-bottom: 8px;
}
.hotspot-item text {
font-size: 14px;
color: #333;
}
.deepmate-action {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #ff4d4f;
padding: 8px 15px;
border-radius: 25px;
margin-top: 10px;
border: none;
}
.stock-input {
flex: 1;
height: 36px;
font-size: 14px;
color: #ffffff;
padding: 0 10px;
border: none;
background-color: transparent;
}
.stock-input::placeholder {
color: rgba(255, 255, 255, 0.8);
}
.send-button-container {
display: flex;
justify-content: center;
align-items: center;
width: 36px;
height: 36px;
background-color: #ffffff;
border-radius: 50%;
margin-left: 10px;
}
.send-button {
width: 20px;
height: 20px;
}
</style>

385
components/MarketOverview.vue

@ -0,0 +1,385 @@
<template>
<view>
<!-- 第一行白色背景标题和按钮 -->
<view class="market-header">
<text class="section-title">今日市场概览</text>
<text class="more-btn" @click="showMarketSelector">{{ buttonText }}</text>
</view>
<!-- 第二行灰色圆角背景市场数据 -->
<view class="market-content">
<!-- 默认显示图片 -->
<view class="selected-market" v-if="!showForexMarket">
<image class="market-image" src="https://d31zlh4on95l9h.cloudfront.net/images/dee46373b5593d5f315d91675a38fb61.png" mode="widthFix"></image>
</view>
<!-- 外汇市场样式 -->
<view class="selected-market" v-if="showForexMarket">
<view class="forex-market">
<!-- 上部分三个汇率容器 -->
<view class="forex-rates">
<view class="forex-rate-item up">
<text class="forex-pair">美元/日元</text>
<text class="forex-value">151.13</text>
<text class="forex-change">+1.62%</text>
</view>
<view class="forex-rate-item down">
<text class="forex-pair">美元/韩元</text>
<text class="forex-value">1424.900</text>
<text class="forex-change">-2.92%</text>
</view>
<view class="forex-rate-item up">
<text class="forex-pair">美元/英镑</text>
<text class="forex-value">0.730</text>
<text class="forex-change">+2.92%</text>
</view>
</view>
<!-- 中部分智能解读标题 -->
<view class="forex-analysis-title">
<text class="analysis-title">智能解读</text>
</view>
<!-- 下部分智能解读内容 -->
<view class="forex-analysis-content">
<view class="analysis-icon-container">
<image class="analysis-brain-icon" src="https://d31zlh4on95l9h.cloudfront.net/images/8f35e54c52412467101370aa70d8fdb2.png" mode="aspectFit"></image>
</view>
<view class="analysis-items">
<view class="analysis-item">
<text class="analysis-dot orange"></text>
<text class="analysis-text">今日市场情报: 偏乐观</text>
</view>
<view class="analysis-item">
<text class="analysis-dot blue"></text>
<text class="analysis-text">市场风险评级: 需警惕潜在风险</text>
</view>
<view class="analysis-item">
<text class="analysis-dot green"></text>
<text class="analysis-text">早盘解析: 今日高开, 芯片稀土公共</text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 市场选择对话框 -->
<uni-popup ref="marketPopup" type="center" :mask-click="true" @change="popupChange">
<view class="market-dialog">
<view class="dialog-title">
<text>选择市场</text>
</view>
<view class="market-list">
<view class="market-option" v-for="(market, index) in marketOptions" :key="index" @click="selectMarket(market.id)">
<view class="market-flag">
<image :src="market.flag" mode="aspectFit" class="flag-image"></image>
</view>
<view class="market-name-container">
<text class="market-option-name">{{ market.name }}</text>
</view>
<view class="market-checkbox">
<radio :checked="selectedMarket === market.id" color="#4080ff" />
</view>
</view>
</view>
<view class="dialog-buttons">
<button class="confirm-btn" @click="confirmMarketSelection">确认</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
export default {
name: 'MarketOverview',
data() {
return {
selectedMarket: 'forex',
tempSelectedMarket: 'forex', //
previousMarket: null,
buttonText: '切换市场',
showSelector: false,
showForexMarket: false, //
marketOptions: [
{ id: 'forex', name: '外汇市场', flag: '/static/c2.png', value: '+1.62%', trend: 'up' }
],
marketData: {
'forex': {
name: '外汇市场',
value: '+1.62%',
trend: 'up',
indicators: [
{ name: '美元/日元', value: '151.13 +1.62%', trend: 'up' },
{ name: '美元/韩元', value: '1424.900 -2.92%', trend: 'down' },
{ name: '美元/英镑', value: '0.79 +2.92%', trend: 'up' }
]
}
}
}
},
methods: {
showMarketSelector() {
//
this.showForexMarket = !this.showForexMarket;
//
this.buttonText = this.showForexMarket ? '外汇市场' : '切换市场';
},
popupChange(e) {
//
if (!e.show && this.tempSelectedMarket !== this.selectedMarket) {
this.tempSelectedMarket = this.selectedMarket;
}
},
selectMarket(marketId) {
//
this.tempSelectedMarket = marketId;
},
confirmMarketSelection() {
//
this.selectedMarket = this.tempSelectedMarket;
this.showSelector = false;
this.$refs.marketPopup.close();
},
getSelectedMarketName() {
if (!this.selectedMarket) return '';
return this.marketData[this.selectedMarket].name;
},
getSelectedMarketValue() {
if (!this.selectedMarket) return '';
return this.marketData[this.selectedMarket].value;
},
getSelectedMarketTrend() {
if (!this.selectedMarket) return '';
return this.marketData[this.selectedMarket].trend;
},
getSelectedMarketIndicators() {
if (!this.selectedMarket) return [];
return this.marketData[this.selectedMarket].indicators;
}
}
}
</script>
<style>
/* 市场概览样式 */
.market-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background-color: #ffffff;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
}
.more-btn {
font-size: 14px;
color: #4080ff;
}
.market-content {
margin: 0 0 15px;
background-color: #f5f7fa;
border-radius: 8px;
overflow: hidden;
}
/* 外汇市场样式 */
.forex-market {
padding: 15px;
}
.forex-rates {
display: flex;
justify-content: space-between;
gap: 10px;
margin-bottom: 15px;
}
.forex-rate-item {
width: 30%;
padding: 10px;
border-radius: 6px;
display: flex;
flex-direction: column;
align-items: center;
}
.forex-rate-item.up {
background-color: rgba(82, 196, 26, 0.1);
border: 1px solid #52c41a;
}
.forex-rate-item.down {
background-color: rgba(245, 34, 45, 0.1);
border: 1px solid #f5222d;
}
.forex-pair {
font-size: 12px;
color: #666;
margin-bottom: 5px;
}
.forex-value {
font-size: 16px;
font-weight: bold;
color: #333;
margin-bottom: 5px;
}
.forex-change {
font-size: 12px;
color: #52c41a;
}
.forex-rate-item.down .forex-change {
color: #f5222d;
}
.forex-analysis-title {
display: flex;
align-items: center;
margin-bottom: 10px;
border-left: 3px solid #f5222d;
padding-left: 8px;
}
.analysis-title {
font-size: 14px;
font-weight: bold;
color: #333;
}
.forex-analysis-content {
display: flex;
background-color: #fff;
border-radius: 6px;
padding: 12px;
}
.analysis-icon-container {
width: 40px;
height: 40px;
margin-right: 10px;
display: flex;
align-items: center;
justify-content: center;
align-self: center;
}
.analysis-brain-icon {
width: 100%;
height: 100%;
}
.analysis-items {
flex: 1;
}
.analysis-item {
display: flex;
align-items: center;
margin-bottom: 8px;
}
.analysis-item:last-child {
margin-bottom: 0;
}
.analysis-dot {
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: 8px;
}
.analysis-dot.orange {
background-color: #fa8c16;
}
.analysis-dot.blue {
background-color: #1890ff;
}
.analysis-dot.green {
background-color: #52c41a;
}
.analysis-text {
font-size: 12px;
color: #333;
line-height: 1.4;
}
/* 市场选择对话框样式 */
.market-dialog {
width: 300px;
background-color: #fff;
border-radius: 10px;
overflow: hidden;
}
.dialog-title {
padding: 15px;
text-align: center;
border-bottom: 1px solid #eee;
}
.market-list {
max-height: 300px;
overflow-y: auto;
}
.market-option {
display: flex;
align-items: center;
padding: 12px 15px;
border-bottom: 1px solid #f5f5f5;
}
.market-flag {
width: 24px;
height: 24px;
margin-right: 10px;
}
.flag-image {
width: 100%;
height: 100%;
border-radius: 50%;
}
.market-name-container {
flex: 1;
}
.market-option-name {
font-size: 14px;
color: #333;
}
.dialog-buttons {
padding: 10px 15px 15px;
display: flex;
justify-content: center;
}
.confirm-btn {
width: 80%;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #4080ff;
color: #fff;
border-radius: 20px;
font-size: 14px;
}
</style>

192
components/footerBar-cn.vue

@ -0,0 +1,192 @@
<template>
<view class="static-footer-bar" :style="{ 'padding-bottom': safeAreaInsets.bottom + 'px' }">
<view class="static-footer-li" @click="tabChange(1)">
<image src="../static/footBar-image/home.png" class="static-footer-li-icon" v-if="type != 'home'"></image>
<image src="../static/footBar-image/home-selected.png" class="static-footer-li-icon" v-if="type == 'home'"></image>
<view :class="type == 'home' ? 'static-footer-li-title1' : 'static-footer-li-title'">
首页</view>
</view>
<view class="static-footer-li" @click="tabChange(2)">
<image src="../static/footBar-image/marketSituation.png" class="static-footer-li-icon" v-if="type != 'marketSituation'">
</image>
<image src="../static/footBar-image/marketSituation-selected.png" class="static-footer-li-icon"
v-if="type == 'marketSituation'"></image>
<view :class="type == 'marketSituation' ? 'static-footer-li-title1' : 'static-footer-li-title'">
行情</view>
</view>
<view class="static-footer-li static-footer-li-special" @click="tabChange(3)">
<image src="../static/footBar-image/deepMate.png" class="static-footer-li-icon static-footer-li-icon-special" v-if="type != 'deepMate'"></image>
<image src="../static/footBar-image/deepMate-selected.png" class="static-footer-li-icon static-footer-li-icon-special" v-if="type == 'deepMate'">
</image>
<view :class="type == 'deepMate' ? 'static-footer-li-title1' : 'static-footer-li-title'">
DeepMate</view>
</view>
<view class="static-footer-li" @click="tabChange(4)">
<image src="../static/footBar-image/deepExploration.png" class="static-footer-li-icon" v-if="type != 'deepExploration'">
</image>
<image src="../static/footBar-image/deepExploration-selected.png" class="static-footer-li-icon"
v-if="type == 'deepExploration'"></image>
<view :class="type == 'deepExploration' ? 'static-footer-li-title1' : 'static-footer-li-title'">
深度探索</view>
</view>
<view class="static-footer-li" @click="tabChange(5)">
<image src="../static/footBar-image/member.png" class="static-footer-li-icon" v-if="type != 'member'"></image>
<image src="../static/footBar-image/member-selected.png" class="static-footer-li-icon" v-if="type == 'member'"></image>
<view :class="type == 'member' ? 'static-footer-li-title1' : 'static-footer-li-title'">
我的</view>
</view>
</view>
</template>
<script setup>
import { computed, onMounted } from 'vue'
// props
const props = defineProps({
type: {
type: String,
default: ''
}
})
//
const safeAreaInsets = computed(() => {
//
const systemInfo = uni.getSystemInfoSync()
return {
bottom: systemInfo.safeAreaInsets?.bottom || 0
}
})
//
const tabChange = (value) => {
// console.log(value)
if (value == 1) { //
uni.redirectTo({
url: '/pages/home/home',
animationType: 'fade-in'
})
} else if (value == 2) { //
uni.redirectTo({
url: '/pages/home/marketSituation',
animationType: 'fade-in'
})
} else if (value == 3) { //DeepMate
uni.redirectTo({
url: '/pages/deepMate/deepMate',
animationType: 'fade-in'
})
} else if (value == 4) { //
if (props.type == 'deepExploration') return;
uni.redirectTo({
url: '/pages/home/deepExploration',
animationType: 'fade-in'
})
} else if (value == 5) { //
if (props.type == 'member') return;
uni.redirectTo({
url: '/pages/home/member',
animationType: 'fade-in'
})
}
}
//
onMounted(() => {
//
})
</script>
<style scoped>
.static-footer-bar {
width: 100%;
height: 120rpx;
border-top: 1px solid #E2E2E2;
background: #fff;
position: relative;
}
.static-footer-li {
display: inline-block;
width: 20%;
height: 100%;
text-align: center;
position: relative;
transform: translateY(-12rpx);
}
.static-footer-li-icon {
width: 46rpx;
height: 46rpx;
margin: 12rpx 0;
}
/* 中间导航项的特殊样式 */
.static-footer-li-special {
position: relative;
z-index: 10;
}
.static-footer-li-icon-special {
width: 95rpx !important;
height: 95rpx !important;
margin: 0rpx 0 !important;
border-radius: 50rpx;
box-shadow: 0 6rpx 20rpx rgba(0, 0, 0, 0.2);
transform: translateY(-12rpx);
transition: all 0.3s ease;
}
.static-footer-li-title {
width: 100%;
height: 40rpx;
line-height: 40rpx;
font-size: 24rpx;
text-align: center;
margin-top: -20rpx;
color: gray;
}
.static-footer-li-title1 {
width: 100%;
height: 40rpx;
line-height: 40rpx;
font-size: 24rpx;
text-align: center;
margin-top: -20rpx;
color: black;
}
.unreadNum {
position: absolute;
right: 15%;
background-color: #f00;
color: #fff;
font-size: 24rpx;
padding: 0 6rpx;
height: 36rpx;
line-height: 36rpx;
min-width: 36rpx;
border-radius: 18rpx;
z-index: 9;
}
.taskNew {
position: absolute;
right: 15%;
height: 30rpx;
z-index: 9;
}
.homeWorkUnRead {
position: absolute;
right: 30%;
top: 10%;
background-color: #f00;
color: #fff;
height: 12rpx;
width: 12rpx;
border-radius: 6rpx;
z-index: 9;
}
</style>

2
components/footerBar.vue

@ -73,7 +73,7 @@ const tabChange = (value) => {
})
} else if (value == 3) { //DeepMate
uni.redirectTo({
url: '/pages/home/deepMate',
url: '/pages/deepMate/deepMate',
animationType: 'fade-in'
})
} else if (value == 4) { //

159
components/login-prompt.vue

@ -0,0 +1,159 @@
<template>
<view class="login-prompt" v-if="showPrompt">
<view
class="mask"
:class="{ 'mask-show': showAnimation }"
></view>
<view class="prompt-content" :class="{ 'slide-up': showAnimation }">
<text class="prompt-title">登录以获得更好的体验</text>
<button class="login-btn" @click="goLogin">登录</button>
<button class="visitor-btn" @click="continueAsVisitor">
以访客身份继续
</button>
<text class="prompt-title-small" @click="goRegister">如果您还没有账号点击注册</text>
</view>
</view>
</template>
<script setup>
import { ref, nextTick } from "vue";
//
const showPrompt = ref(false);
const showAnimation = ref(false);
//
const show = () => {
showPrompt.value = true;
//
nextTick(() => {
setTimeout(() => {
showAnimation.value = true;
}, 10);
});
};
//
const hide = () => {
showAnimation.value = false;
//
setTimeout(() => {
showPrompt.value = false;
}, 300);
};
//
const goLogin = () => {
uni.navigateTo({
url: "/pages/start/login/login",
});
hide();
};
//
const goRegister = () => {
uni.navigateTo({
url: "/pages/start/Registration/Registration",
});
hide();
};
// 访
const continueAsVisitor = () => {
// 访
uni.setStorageSync("visitorMode", true);
hide();
};
// 使
defineExpose({
show,
hide,
});
</script>
<style scoped>
.login-prompt {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 999;
}
.mask {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.8);
opacity: 0;
transition: opacity 0.3s ease;
}
.mask.mask-show {
opacity: 1;
}
.prompt-content {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 400rpx;
border-radius: 20rpx 20rpx 0 0;
background-color: white;
padding: 20rpx 70rpx;
transform: translateY(100%);
transition: transform 0.3s ease;
box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.3);
}
.prompt-content.slide-up {
transform: translateY(0);
}
.prompt-title {
display: block;
text-align: center;
font-size: 40rpx;
font-weight: 700;
color: #000000;
margin-top: 30rpx;
margin-bottom: 40rpx;
}
.login-btn {
width: 100%;
height: 80rpx;
background-color: rgb(0, 0, 0);
color: white;
font-size: 32rpx;
line-height: 80rpx;
border-radius: 40rpx;
margin-bottom: 20rpx;
}
.visitor-btn {
width: 100%;
height: 80rpx;
background-color: #f5f5f5;
color: #333;
font-size: 32rpx;
line-height: 80rpx;
border-radius: 40rpx;
}
.prompt-title-small {
display: block;
text-align: center;
font-size: 24rpx;
color: #6a6a6a;
margin-top: 30rpx;
margin-bottom: 40rpx;
line-height: 15.5px;
letter-spacing: 0.3px;
font-style: normal;
font-family: "PingFang SC";
}
</style>

110
main.js

@ -1,109 +1,39 @@
import App from './App'
import pinia from './stores/index.js'
// #ifndef VUE3
import Vue from 'vue'
import App from './App'
import './uni.promisify.adaptor'
// 导入需要全局注册的组件
import LoginPrompt from './components/login-prompt.vue'
Vue.config.productionTip = false
// 全局注册组件
Vue.component('LoginPrompt', LoginPrompt)
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
...App,
// 挂载 store
pinia
})
app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
import App from './App.vue'
import { createI18n } from 'vue-i18n'
// 导入需要全局注册的组件
import LoginPrompt from './components/login-prompt.vue'
// 导入语言文件
import en from './static/language/en.js'
import ms from './static/language/ms.js'
import th from './static/language/th.js'
import vi from './static/language/vi.js'
import zh_CN from './static/language/zh_CN.js'
import zh_HK from './static/language/zh_HK.js'
function getCurrentLocale() {
if (uni.getStorageSync('languageData') && uni.getStorageSync('languageData').code && uni
.getStorageSync('languageData').code != 'undefined') {
return uni.getStorageSync('languageData').code;
} else {
let language = uni.getSystemInfoSync().osLanguage;
// language = 'zh_CN'
if (language.indexOf('th') != -1) {
language = 'th'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else if (language.indexOf('vi') != -1) {
language = 'vi'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
}else if (language.indexOf('zh') != -1) {
if (language.indexOf('CN') != -1) {
language = 'zh_CN'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else {
language = 'zh_HK'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
}
} else if (language.indexOf('en') != -1) {
language = 'en'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else if (language.indexOf('ms') != -1) {
language = 'ms'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else {
language = 'en'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
}
}
}
// 创建 i18n 实例
const i18n = createI18n({
locale: getCurrentLocale(),
legacy: false, // 使用 Composition API 模式
globalInjection: true, // 全局注入 $t 函数
messages: {
'en': en,
'ms': ms,
'th': th,
'vi': vi,
'zh_CN': zh_CN,
'zh_HK': zh_HK
}
})
export function createApp() {
const app = createSSRApp(App)
app.use(i18n)
// 全局注册组件
app.component('LoginPrompt', LoginPrompt)
// 挂载 store
app.use(pinia)
return {
app
}

116
main.js.bgk

@ -0,0 +1,116 @@
// #ifndef VUE3
import Vue from 'vue'
import App from './App'
import LoginPrompt from './components/login-prompt.vue'
Vue.component('LoginPrompt', LoginPrompt)
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
import App from './App.vue'
import { createI18n } from 'vue-i18n'
import LoginPrompt from './components/login-prompt.vue'
// 导入语言文件
import en from './static/language/en.js'
import ms from './static/language/ms.js'
import th from './static/language/th.js'
import vi from './static/language/vi.js'
import zh_CN from './static/language/zh_CN.js'
import zh_HK from './static/language/zh_HK.js'
function getCurrentLocale() {
if (uni.getStorageSync('languageData') && uni.getStorageSync('languageData').code && uni
.getStorageSync('languageData').code != 'undefined') {
return uni.getStorageSync('languageData').code;
} else {
let language = uni.getSystemInfoSync().osLanguage;
// language = 'zh_CN'
if (language.indexOf('th') != -1) {
language = 'th'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else if (language.indexOf('vi') != -1) {
language = 'vi'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else if (language.indexOf('zh') != -1) {
if (language.indexOf('CN') != -1) {
language = 'zh_CN'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else {
language = 'zh_HK'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
}
} else if (language.indexOf('en') != -1) {
language = 'en'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else if (language.indexOf('ms') != -1) {
language = 'ms'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
} else {
language = 'en'
uni.setStorageSync('languageData', {
code: language
})
console.log(language);
return language
}
}
}
// 创建 i18n 实例
const i18n = createI18n({
locale: getCurrentLocale(),
legacy: false, // 使用 Composition API 模式
globalInjection: true, // 全局注入 $t 函数
messages: {
'en': en,
'ms': ms,
'th': th,
'vi': vi,
'zh_CN': zh_CN,
'zh_HK': zh_HK
}
})
export function createApp() {
const app = createSSRApp(App)
app.component('LoginPrompt', LoginPrompt)
app.use(i18n)
return {
app
}
}
// #endif

13
manifest.json

@ -16,7 +16,9 @@
"autoclose" : true,
"delay" : 0
},
"modules" : {},
"modules" : {
"OAuth" : {}
},
/* */
"distribute" : {
/* */
@ -42,7 +44,14 @@
},
"ios" : {},
/* ios */
"sdkConfigs" : {}
"sdkConfigs" : {
"oauth" : {
"apple" : {},
"google" : {
"clientid" : "135"
}
}
}
}
},
/* SDK */

857
package-lock.json

@ -0,0 +1,857 @@
{
"name": "deepChartVueApp",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"json-server": "^1.0.0-beta.3",
"marked": "^2.0.1",
"pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.5.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.28.5",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.28.5",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/types": "^7.28.5"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/types": {
"version": "7.28.5",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.28.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.5",
"license": "MIT",
"peer": true
},
"node_modules/@polka/url": {
"version": "1.0.0-next.29",
"license": "MIT"
},
"node_modules/@tinyhttp/accepts": {
"version": "2.2.3",
"license": "MIT",
"dependencies": {
"mime": "4.0.4",
"negotiator": "^0.6.3"
},
"engines": {
"node": ">=12.20.0"
},
"funding": {
"type": "individual",
"url": "https://github.com/tinyhttp/tinyhttp?sponsor=1"
}
},
"node_modules/@tinyhttp/app": {
"version": "2.5.2",
"license": "MIT",
"dependencies": {
"@tinyhttp/cookie": "2.1.1",
"@tinyhttp/proxy-addr": "2.2.1",
"@tinyhttp/req": "2.2.5",
"@tinyhttp/res": "2.2.5",
"@tinyhttp/router": "2.2.3",
"header-range-parser": "1.1.3",
"regexparam": "^2.0.2"
},
"engines": {
"node": ">=14.21.3"
},
"funding": {
"type": "individual",
"url": "https://github.com/tinyhttp/tinyhttp?sponsor=1"
}
},
"node_modules/@tinyhttp/content-disposition": {
"version": "2.2.2",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
},
"funding": {
"type": "individual",
"url": "https://github.com/tinyhttp/tinyhttp?sponsor=1"
}
},
"node_modules/@tinyhttp/content-type": {
"version": "0.1.4",
"license": "MIT",
"engines": {
"node": ">=12.4"
}
},
"node_modules/@tinyhttp/cookie": {
"version": "2.1.1",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
},
"funding": {
"type": "individual",
"url": "https://github.com/tinyhttp/tinyhttp?sponsor=1"
}
},
"node_modules/@tinyhttp/cookie-signature": {
"version": "2.1.1",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/cors": {
"version": "2.0.1",
"license": "MIT",
"dependencies": {
"@tinyhttp/vary": "^0.1.3"
},
"engines": {
"node": ">=12.20 || 14.x || >=16"
}
},
"node_modules/@tinyhttp/encode-url": {
"version": "2.1.1",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/etag": {
"version": "2.1.2",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/forwarded": {
"version": "2.1.2",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/logger": {
"version": "2.1.0",
"license": "MIT",
"dependencies": {
"colorette": "^2.0.20",
"dayjs": "^1.11.13",
"http-status-emojis": "^2.2.0"
},
"engines": {
"node": ">=14.18 || >=16.20"
}
},
"node_modules/@tinyhttp/proxy-addr": {
"version": "2.2.1",
"license": "MIT",
"dependencies": {
"@tinyhttp/forwarded": "2.1.2",
"ipaddr.js": "^2.2.0"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/req": {
"version": "2.2.5",
"license": "MIT",
"dependencies": {
"@tinyhttp/accepts": "2.2.3",
"@tinyhttp/type-is": "2.2.4",
"@tinyhttp/url": "2.1.1",
"header-range-parser": "^1.1.3"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/res": {
"version": "2.2.5",
"license": "MIT",
"dependencies": {
"@tinyhttp/content-disposition": "2.2.2",
"@tinyhttp/cookie": "2.1.1",
"@tinyhttp/cookie-signature": "2.1.1",
"@tinyhttp/encode-url": "2.1.1",
"@tinyhttp/req": "2.2.5",
"@tinyhttp/send": "2.2.3",
"@tinyhttp/vary": "^0.1.3",
"es-escape-html": "^0.1.1",
"mime": "4.0.4"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/router": {
"version": "2.2.3",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/send": {
"version": "2.2.3",
"license": "MIT",
"dependencies": {
"@tinyhttp/content-type": "^0.1.4",
"@tinyhttp/etag": "2.1.2",
"mime": "4.0.4"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/type-is": {
"version": "2.2.4",
"license": "MIT",
"dependencies": {
"@tinyhttp/content-type": "^0.1.4",
"mime": "4.0.4"
},
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/url": {
"version": "2.1.1",
"license": "MIT",
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/@tinyhttp/vary": {
"version": "0.1.3",
"license": "MIT",
"engines": {
"node": ">=12.20"
}
},
"node_modules/@vue/compiler-core": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/parser": "^7.28.4",
"@vue/shared": "3.5.22",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-core": "3.5.22",
"@vue/shared": "3.5.22"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/parser": "^7.28.4",
"@vue/compiler-core": "3.5.22",
"@vue/compiler-dom": "3.5.22",
"@vue/compiler-ssr": "3.5.22",
"@vue/shared": "3.5.22",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.19",
"postcss": "^8.5.6",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.22",
"@vue/shared": "3.5.22"
}
},
"node_modules/@vue/devtools-api": {
"version": "7.7.7",
"license": "MIT",
"dependencies": {
"@vue/devtools-kit": "^7.7.7"
}
},
"node_modules/@vue/devtools-kit": {
"version": "7.7.7",
"license": "MIT",
"dependencies": {
"@vue/devtools-shared": "^7.7.7",
"birpc": "^2.3.0",
"hookable": "^5.5.3",
"mitt": "^3.0.1",
"perfect-debounce": "^1.0.0",
"speakingurl": "^14.0.1",
"superjson": "^2.2.2"
}
},
"node_modules/@vue/devtools-shared": {
"version": "7.7.7",
"license": "MIT",
"dependencies": {
"rfdc": "^1.4.1"
}
},
"node_modules/@vue/reactivity": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/shared": "3.5.22"
}
},
"node_modules/@vue/runtime-core": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/reactivity": "3.5.22",
"@vue/shared": "3.5.22"
}
},
"node_modules/@vue/runtime-dom": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/reactivity": "3.5.22",
"@vue/runtime-core": "3.5.22",
"@vue/shared": "3.5.22",
"csstype": "^3.1.3"
}
},
"node_modules/@vue/server-renderer": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-ssr": "3.5.22",
"@vue/shared": "3.5.22"
},
"peerDependencies": {
"vue": "3.5.22"
}
},
"node_modules/@vue/shared": {
"version": "3.5.22",
"license": "MIT",
"peer": true
},
"node_modules/birpc": {
"version": "2.6.1",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/chalk": {
"version": "5.6.2",
"license": "MIT",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/chokidar": {
"version": "4.0.3",
"license": "MIT",
"dependencies": {
"readdirp": "^4.0.1"
},
"engines": {
"node": ">= 14.16.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/colorette": {
"version": "2.0.20",
"license": "MIT"
},
"node_modules/copy-anything": {
"version": "4.0.5",
"license": "MIT",
"dependencies": {
"is-what": "^5.2.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/csstype": {
"version": "3.1.3",
"license": "MIT",
"peer": true
},
"node_modules/dayjs": {
"version": "1.11.18",
"license": "MIT"
},
"node_modules/deep-pick-omit": {
"version": "1.2.1",
"license": "MIT"
},
"node_modules/defu": {
"version": "6.1.4",
"license": "MIT"
},
"node_modules/destr": {
"version": "2.0.5",
"license": "MIT"
},
"node_modules/dot-prop": {
"version": "9.0.0",
"license": "MIT",
"dependencies": {
"type-fest": "^4.18.2"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/entities": {
"version": "4.5.0",
"license": "BSD-2-Clause",
"peer": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/es-escape-html": {
"version": "0.1.1",
"license": "MIT",
"engines": {
"node": ">=12.x"
}
},
"node_modules/estree-walker": {
"version": "2.0.2",
"license": "MIT",
"peer": true
},
"node_modules/eta": {
"version": "3.5.0",
"license": "MIT",
"engines": {
"node": ">=6.0.0"
},
"funding": {
"url": "https://github.com/eta-dev/eta?sponsor=1"
}
},
"node_modules/header-range-parser": {
"version": "1.1.3",
"license": "MIT",
"engines": {
"node": ">=12.22.0"
}
},
"node_modules/hookable": {
"version": "5.5.3",
"license": "MIT"
},
"node_modules/http-status-emojis": {
"version": "2.2.0",
"license": "MIT"
},
"node_modules/inflection": {
"version": "3.0.2",
"license": "MIT",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/ipaddr.js": {
"version": "2.2.0",
"license": "MIT",
"engines": {
"node": ">= 10"
}
},
"node_modules/is-what": {
"version": "5.5.0",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/json-server": {
"version": "1.0.0-beta.3",
"license": "SEE LICENSE IN ./LICENSE",
"dependencies": {
"@tinyhttp/app": "^2.4.0",
"@tinyhttp/cors": "^2.0.1",
"@tinyhttp/logger": "^2.0.0",
"chalk": "^5.3.0",
"chokidar": "^4.0.1",
"dot-prop": "^9.0.0",
"eta": "^3.5.0",
"inflection": "^3.0.0",
"json5": "^2.2.3",
"lowdb": "^7.0.1",
"milliparsec": "^4.0.0",
"sirv": "^2.0.4",
"sort-on": "^6.1.0"
},
"bin": {
"json-server": "lib/bin.js"
},
"engines": {
"node": ">=18.3"
}
},
"node_modules/json5": {
"version": "2.2.3",
"license": "MIT",
"bin": {
"json5": "lib/cli.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/lowdb": {
"version": "7.0.1",
"license": "MIT",
"dependencies": {
"steno": "^4.0.2"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/magic-string": {
"version": "0.30.21",
"license": "MIT",
"peer": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/marked": {
"version": "2.0.1",
"license": "MIT",
"bin": {
"marked": "bin/marked"
},
"engines": {
"node": ">= 8.16.2"
}
},
"node_modules/milliparsec": {
"version": "4.0.0",
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/mime": {
"version": "4.0.4",
"funding": [
"https://github.com/sponsors/broofa"
],
"license": "MIT",
"bin": {
"mime": "bin/cli.js"
},
"engines": {
"node": ">=16"
}
},
"node_modules/mitt": {
"version": "3.0.1",
"license": "MIT"
},
"node_modules/mrmime": {
"version": "2.0.1",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/nanoid": {
"version": "3.3.11",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"peer": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/negotiator": {
"version": "0.6.4",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/perfect-debounce": {
"version": "1.0.0",
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.1.1",
"license": "ISC",
"peer": true
},
"node_modules/pinia": {
"version": "3.0.3",
"license": "MIT",
"dependencies": {
"@vue/devtools-api": "^7.7.2"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"typescript": ">=4.4.4",
"vue": "^2.7.0 || ^3.5.11"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/pinia-plugin-persistedstate": {
"version": "4.5.0",
"license": "MIT",
"dependencies": {
"deep-pick-omit": "^1.2.1",
"defu": "^6.1.4",
"destr": "^2.0.5"
},
"peerDependencies": {
"@nuxt/kit": ">=3.0.0",
"@pinia/nuxt": ">=0.10.0",
"pinia": ">=3.0.0"
},
"peerDependenciesMeta": {
"@nuxt/kit": {
"optional": true
},
"@pinia/nuxt": {
"optional": true
},
"pinia": {
"optional": true
}
}
},
"node_modules/postcss": {
"version": "8.5.6",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/postcss"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
"engines": {
"node": "^10 || ^12 || >=14"
}
},
"node_modules/readdirp": {
"version": "4.1.2",
"license": "MIT",
"engines": {
"node": ">= 14.18.0"
},
"funding": {
"type": "individual",
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/regexparam": {
"version": "2.0.2",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/rfdc": {
"version": "1.4.1",
"license": "MIT"
},
"node_modules/sirv": {
"version": "2.0.4",
"license": "MIT",
"dependencies": {
"@polka/url": "^1.0.0-next.24",
"mrmime": "^2.0.0",
"totalist": "^3.0.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/sort-on": {
"version": "6.1.1",
"license": "MIT",
"dependencies": {
"dot-prop": "^9.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/source-map-js": {
"version": "1.2.1",
"license": "BSD-3-Clause",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/speakingurl": {
"version": "14.0.1",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/steno": {
"version": "4.0.2",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/superjson": {
"version": "2.2.3",
"license": "MIT",
"dependencies": {
"copy-anything": "^4"
},
"engines": {
"node": ">=16"
}
},
"node_modules/totalist": {
"version": "3.0.1",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/type-fest": {
"version": "4.41.0",
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/vue": {
"version": "3.5.22",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.22",
"@vue/compiler-sfc": "3.5.22",
"@vue/runtime-dom": "3.5.22",
"@vue/server-renderer": "3.5.22",
"@vue/shared": "3.5.22"
},
"peerDependencies": {
"typescript": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
}
}
}

12
package.json

@ -0,0 +1,12 @@
{
"dependencies": {
"json-server": "^1.0.0-beta.3",
"marked": "^2.0.1",
"pinia": "^3.0.3",
"pinia-plugin-persistedstate": "^4.5.0"
},
"scripts": {
"server-login": "json-server ./server/login.json --port 8888",
"server-deepchart": "json-server ./server/deepchart.json --port 8888"
}
}

119
pages.json

@ -1,5 +1,90 @@
{
"pages": [
"pages": [{
"path": "pages/start/startup/startup",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"navigationBarBackgroundColor": "#000000",
"navigationBarTextStyle": "white",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/start/select/select",
"style": {
"navigationBarBackgroundColor": "#000000",
"navigationBarTitleText": "",
"animationType": "pop-in",
"navigationStyle": "custom",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/start/index/index",
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "uni-app",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/start/Registration/Registration",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/start/login/login",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/start/agreement/agreement",
"style": {
"navigationBarTitleText": "",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/start/privacy/privacy",
"style": {
"navigationBarTitleText": "",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/deepMate/deepMate",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/home/home",
"style": {
@ -44,6 +129,32 @@
"titleNView": false,
"bounce": false
}
},
{
"path": "pages/blank/blank",
"style": {
"navigationBarTitleText": "",
"navigationStyle": "custom",
"disableSwipeBack": true,
"titleNView": false,
"bounce": false
}
},
{
"path" : "pages/start/recoverPassword/recoverPassword",
"style" :
{
"navigationBarTitleText": "",
"navigationStyle": "custom",
"titleNView": false
}
},
{
"path" : "pages/deepMate/scroll/scroll",
"style" :
{
"navigationBarTitleText" : ""
}
}
],
"globalStyle": {
@ -54,5 +165,11 @@
"app-plus": {
"background": "#efeff4"
}
},
"style": {
"app-plus": {
"animationType": "fade-in",
"animationDuration": 500
}
}
}

23
pages/blank/blank.vue

@ -0,0 +1,23 @@
<template>
<view class="blank-page">
<text class="tip">当前特斯拉该如何布局</text>
</view>
</template>
<script setup>
//
</script>
<style scoped>
.blank-page {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
background-color: #ffffff;
}
.tip {
color: #999999;
font-size: 28rpx;
}
</style>

1524
pages/deepMate/deepMate.vue
File diff suppressed because it is too large
View File

63
pages/deepMate/scroll/scroll.vue

@ -0,0 +1,63 @@
<template>
<view class="container">
<scroll-view
class="scroll-view"
scroll-y="true"
@scrolltolower="onScrollToLower"
>
<button @click="scrollTo">点击滚动</button>
<view v-for="(item, index) in list" :key="index">
{{ item }}
</view>
</scroll-view>
<button @click="addItem">添加内容</button>
</view>
</template>
<script>
export default {
data() {
return {
list: Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`),
};
},
methods: {
onScrollToLower() {
console.log("滚动到底部了");
//
},
addItem() {
this.list.push(`Item ${this.list.length + 1}`);
this.$nextTick(() => {
this.$refs.scrollView.scrollTo({
top: 99999,
duration: 300,
});
});
},
scrollTo() {
uni.pageScrollTo({
scrollTop: 100,
duration: 300,
});
},
},
};
</script>
<style>
.container {
height: 100%;
}
.scroll-view {
height: 80%;
}
button {
width: 100%;
height: 50px;
line-height: 50px;
text-align: center;
background-color: #007aff;
color: white;
}
</style>

699
pages/home/home.vue

@ -2,27 +2,708 @@
<view class="main">
<!-- 顶部状态栏占位 -->
<view class="top" :style="{height:iSMT+'px'}"></view>
<view>首页</view>
<!-- 头部导航 -->
<view class="header">
<view class="headphone-icon">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/bef2edba6cc0c85671fde07cfab5270d.png" class="header-icon-image"></image>
</view>
<view class="title">DeepChart</view>
<view class="notification-icon">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/2554c84b91712d2a6cb6b00380e63bac.png" class="header-icon-image"></image>
</view>
</view>
<!-- 内容区域 - 使用滚动视图 -->
<scroll-view scroll-y class="content-container">
<!-- 1. 今日市场概览 -->
<market-overview></market-overview>
<!-- 间隔 -->
<view class="section-gap"></view>
<!-- 新增欢迎部分 -->
<view class="section welcome-section">
<!-- 轮播图 -->
<swiper class="welcome-swiper" circular autoplay interval="3000" duration="500" indicator-dots indicator-active-color="#4080ff">
<swiper-item v-for="(item, index) in 5" :key="index">
<image class="swiper-image" src="https://d31zlh4on95l9h.cloudfront.net/images/e4272cc034fa2a3d1ca588ef84e51ab0.png" mode="aspectFill"></image>
</swiper-item>
</swiper>
</view>
<!-- 2. DeepMate -->
<view class="section deepmate-section">
<DeepMate />
</view>
<!-- 3. 深度探索 -->
<view class="section deep-exploration">
<!-- 上部分标题和查看更多按钮 -->
<view class="section-header-container">
<view class="section-header">
<view class="header-left">
<text class="section-title">深度探索</text>
</view>
<view class="header-right">
<text class="more-btn">查看更多</text>
</view>
</view>
</view>
<!-- 下部分四个图标 -->
<view class="exploration-container">
<view class="exploration-content">
<view class="exploration-item">
<image class="exploration-icon" src="https://d31zlh4on95l9h.cloudfront.net/images/199472b0ee90a1c897f7c87b85accd84.png" mode="aspectFit" lazy-load="true"></image>
<text class="exploration-text">主力追踪</text>
</view>
<view class="exploration-item">
<image class="exploration-icon" src="https://d31zlh4on95l9h.cloudfront.net/images/c25ca5e176efc961dabfa5d0d1b486b0.png" mode="aspectFit" lazy-load="true"></image>
<text class="exploration-text">主力资达</text>
</view>
<view class="exploration-item">
<image class="exploration-icon" src="https://d31zlh4on95l9h.cloudfront.net/images/c064d7066dc8129a7df7b052762f82cf.png" mode="aspectFit" lazy-load="true"></image>
<text class="exploration-text">主力解码</text>
</view>
<view class="exploration-item">
<image class="exploration-icon" src="https://d31zlh4on95l9h.cloudfront.net/images/9d69cceee9c515911477078af6f68d88.png" mode="aspectFit" lazy-load="true"></image>
<text class="exploration-text">主力资金流</text>
</view>
</view>
</view>
</view>
<!-- 4. 我的自选 -->
<view class="section my-selection">
<!-- 上部分标题和查看更多按钮 -->
<view class="section-header-container">
<view class="section-header">
<text class="section-title">我的自选</text>
<text class="more-btn">添加自选股</text>
</view>
</view>
<!-- 下部分股票列表 -->
<view class="stock-container">
<view class="stock-list">
<view class="stock-item" v-for="(item, index) in myStocks" :key="item.code">
<view class="stock-info">
<view class="name-container">
<text class="stock-name">{{item.name}}</text>
<text class="stock-code-label">{{item.code}}</text>
</view>
<view class="price-container">
<text class="stock-price">{{item.price}}</text>
<text class="stock-change" :class="{'stock-up': item.change > 0, 'stock-down': item.change < 0}">{{item.change > 0 ? '+' : ''}}{{item.change}}%</text>
</view>
</view>
<view class="stock-chart">
<image :src="item.chartImg" mode="aspectFit" class="chart-image"></image>
</view>
</view>
</view>
<!-- 机构动向简报数据 -->
<view class="institutional-reports">
<view class="section-title-container">
<text class="section-title-text">机构动向简报</text>
</view>
<view class="text-gap"></view>
<view class="report-item" v-for="(report, index) in institutionalReports" :key="index">
<view class="report-stock">{{report.stock}}</view>
<view class="report-status">{{report.status}}</view>
</view>
<view class="view-more">
<text>查看更多 >></text>
</view>
</view>
</view>
</view>
<!-- 5. 今日市场看点 -->
<view class="section-header highlights-title-container">
<text class="section-title">今日市场核心看点</text>
</view>
<view class="highlights-image-container">
<image src="https://d31zlh4on95l9h.cloudfront.net/images/8d5365af968402a18cedb120c09460b0.png" mode="aspectFit" class="highlights-image"></image>
</view>
<!-- 底部空间 - 为底部导航腾出空间 -->
<view class="bottom-space"></view>
</scroll-view>
<!-- 底部导航 -->
<footerBar class="static-footer" :type="type"></footerBar>
</view>
</template>
<script setup>
import { ref,onMounted } from 'vue'
<script>
import footerBar from '../../components/footerBar.vue'
import MarketOverview from '../../components/MarketOverview.vue'
import DeepMate from '../../components/DeepMate.vue'
const type = ref('home')
const iSMT = ref(0)
export default {
components: {
footerBar,
MarketOverview,
DeepMate
},
data() {
return {
type: 'home',
iSMT: 0,
//
explorationItems: [
{ title: '主力追踪', icon: '/static/c1.png' },
{ title: '主力资金', icon: '/static/c2.png' },
{ title: '主力解码', icon: '/static/c3.png' },
{ title: '主力资金流', icon: '/static/c4.png' }
],
//
myStocks: [
{ name: '特斯拉', code: 'TSLA', price: '482.00', change: 2.80, chartImg: '/static/c5.png' },
{ name: '英伟达', code: 'NVDA', price: '189.800', change: -2.92, chartImg: '/static/c6.png' },
{ name: '苹果', code: 'AAPL', price: '256.430', change: 2.60, chartImg: '/static/c7.png' }
],
//
institutionalReports: [
{ stock: '特斯拉', status: '当前市场多头资金占比,且多头资金持续流入。' },
{ stock: '英伟达', status: '当前市场多头资金占比,且多头资金持续流入。' },
{ stock: '苹果', status: '当前市场多头资金占比,且多头资金持续流入。' }
],
//
debounceTimer: null
}
},
onMounted(() => {
//
iSMT.value = uni.getSystemInfoSync().statusBarHeight;
})
// Vue 2
mounted() {
//
this.iSMT = uni.getSystemInfoSync().statusBarHeight;
//
this.myStocks.forEach(stock => {
// 使uni.getImageInfoImage
uni.getImageInfo({
src: stock.chartImg,
success: function(res) {
//
console.log('图片预加载成功:', stock.name)
},
fail: function(err) {
console.log('图片预加载失败:', err)
}
})
})
},
methods: {
//
debounce(fn, delay = 300) {
if (this.debounceTimer) clearTimeout(this.debounceTimer)
this.debounceTimer = setTimeout(() => {
fn()
this.debounceTimer = null
}, delay)
}
}
}
</script>
<style scoped>
.main {
display: flex;
flex-direction: column;
height: 100vh;
background-color: #ffffff;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background-color: #ffffff;
}
.title {
font-size: 22px;
font-weight: bold;
text-align: center;
flex: 1;
}
.headphone-icon, .notification-icon {
width: 40px;
display: flex;
align-items: center;
justify-content: center;
}
.header-icon-image {
width: 24px;
height: 24px;
object-fit: contain;
}
.content-container {
flex: 1;
padding: 10px;
width: 100%;
box-sizing: border-box;
overflow-x: hidden;
}
.section {
margin-bottom: 15px;
/* background-color: #f5f5f5; */
background-color: #ffffff;
border-radius: 8px;
padding: 15px;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding-bottom: 10px;
}
.section-title {
font-size: 18px;
font-weight: bold;
color: #000000;
}
.section-title-text{
font-size: 14px;
}
.text-gap{
height: 10px;
}
.more-btn {
font-size: 12px;
font-weight: bold;
color: #ffffff;
background-color: #000000;
padding: 4px 8px;
border-radius: 4px;
}
/* 市场概览样式 */
.market-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background-color: #ffffff;
margin-bottom: 10px;
}
.market-content {
background-color: #f5f5f5;
border-radius: 8px;
padding: 15px;
margin: 0 15px;
}
.market-image {
margin-bottom: 15px;
display: flex;
justify-content: center;
}
.overview-image {
width: 100%;
border-radius: 8px;
}
.market-data {
display: flex;
flex-direction: column;
gap: 10px;
}
/* 间隔样式 */
.section-gap {
height: 20px;
}
.market-item {
display: flex;
justify-content: space-between;
padding: 8px 0;
border-bottom: 1px solid #f0f0f0;
}
.down {
color: #ff4d4f;
}
.up {
color: #52c41a;
}
/* DeepMate样式 */
.deepmate-container {
background-color: #ffe6e6;
border-radius: 10px;
padding: 15px;
margin: 0 15px;
}
.deepmate-header {
margin-bottom: 10px;
}
.title-container {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.title-left {
width: 50%;
}
.title-right {
width: 50%;
display: flex;
justify-content: flex-end;
}
.deepmate-title {
font-size: 18px;
font-weight: bold;
color: #ff4d4f;
}
.deepmate-icon {
width: 60px;
height: 60px;
margin-left: 0;
}
.deepmate-subtitle {
font-size: 12px;
color: #666;
margin-left: 5px;
}
.deepmate-hotspots {
margin: 10px 0;
}
.hotspot-item {
background-color: #f5f5f5;
padding: 8px 12px;
border-radius: 6px;
margin-bottom: 8px;
}
.hotspot-item text {
font-size: 14px;
color: #333;
}
.deepmate-action {
display: flex;
justify-content: center;
align-items: center;
background-color: #ffffff;
border-radius: 20px;
padding: 10px;
margin-top: 10px;
}
/* 欢迎部分样式 */
.welcome-section {
margin-bottom: 15px;
padding: 0;
}
.welcome-swiper {
width: 100%;
height: 150px;
border-radius: 0;
overflow: hidden;
}
.deepmate-section {
padding: 0;
}
.swiper-image {
width: 100%;
height: 100%;
border-radius: 8px;
object-fit: contain;
}
/* 深度探索样式 */
.deep-exploration {
margin-top: 15px;
padding: 0; /* 移除内边距,让子容器自己控制 */
}
.section-header-container {
margin-bottom: 10px;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background-color: #ffffff;
}
.header-left {
display: flex;
align-items: center;
}
.header-right {
display: flex;
align-items: center;
}
.section-title {
font-size: 16px;
font-weight: bold;
color: #333;
}
.more-btn {
font-size: 12px;
color: #ffffff;
}
.exploration-container {
border-radius: 8px;
overflow: hidden;
}
.exploration-content {
display: flex;
justify-content: space-between;
padding: 15px;
background-color: #f5f5f5;
border-radius: 8px;
}
.exploration-item {
display: flex;
flex-direction: column;
align-items: center;
width: 22%;
background-color: #ffffff;
border-radius: 8px;
padding: 10px 0;
}
.exploration-icon {
width: 50px;
height: 50px;
margin-bottom: 8px;
}
.exploration-text {
font-size: 12px;
color: #333;
}
.icon-text {
font-size: 12px;
}
/* 我的自选样式 */
.my-selection {
padding: 0; /* 移除内边距,让子容器自己控制 */
}
.stock-container {
border-radius: 8px;
overflow: hidden;
background-color: #f5f5f5;
padding: 15px;
box-sizing: border-box;
}
.stock-list {
display: flex;
flex-direction: row;
justify-content: center;
background-color: #f8f8f8;
border-radius: 8px;
padding: 15px;
gap: 10px; /* 添加卡片之间的间距 */
}
.stock-item {
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 3px;
background-color: #ffffff;
border-radius: 8px;
width: 30%;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
will-change: transform;
transform: translateZ(0);
}
.stock-info {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 5px;
}
.stock-chart {
display: flex;
align-items: center;
justify-content: center;
}
.name-container {
display: flex;
align-items: center;
gap: 5px;
}
.stock-name {
font-size: 12px;
font-weight: bold;
color: #333;
}
.stock-code-label {
font-size: 12px;
color: #666;
background-color: #f5f5f5;
padding: 0 4px;
border-radius: 3px;
}
.stock-price {
font-size: 12px;
color: #666;
}
.price-container {
display: flex;
align-items: center;
gap: 5px;
}
.stock-change {
font-size: 12px;
}
.stock-up {
color: #4cd964;
}
.stock-down {
color: #ff3b30;
}
.chart-image {
width: 100px;
height: 40px;
}
/* 市场看点样式 */
.highlights-title-container {
background-color: #ffffff;
margin-bottom: 10px;
}
.highlights-image-container {
background-color: #f5f5f5;
border-radius: 8px;
padding: 10px;
margin-bottom: 15px;
}
.highlights-image {
width: 100%;
height: 150px;
border-radius: 4px;
}
/* 机构动向简报样式 */
.institutional-reports {
margin-top: 15px;
background-color: #f8f8f8;
border-radius: 8px;
padding: 10px;
}
.section-title-container {
position: relative;
padding-left: 10px;
margin-bottom: 5px;
}
.section-title-container:before {
content: "";
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 4px;
background-color: #ff4d4f;
border-radius: 2px;
}
.report-item {
background-color: #ffffff;
border-radius: 8px;
padding: 10px;
margin-bottom: 8px;
}
.report-stock {
font-size: 14px;
font-weight: bold;
color: #e74c3c;
margin-bottom: 5px;
}
.report-status {
font-size: 12px;
color: #333;
}
.view-more {
text-align: center;
color: #1890ff;
font-size: 12px;
padding: 5px;
}
/* 底部空间 */
.bottom-space {
height: 60px;
}
/* 底部导航 */
.static-footer {
position: fixed;
bottom: 0;
width: 100%;
}
</style>

949
pages/start/Registration/Registration.vue

@ -0,0 +1,949 @@
<template>
<view class="login-registration-container">
<!-- 自定义导航栏 -->
<view
class="custom-navbar"
:style="{ paddingTop: safeAreaInsets?.top + 'px' }"
>
<!-- <view class="nav-left">
<text class="back-btn" @click="goToIndex"></text>
</view> -->
<view class="nav-right">
<image
class="icons"
src="../../../static/icons/Headset.png"
alt="联系客服"
/>
<image
class="icons"
@click="goToIndex"
src="../../../static/icons/Frame.png"
alt="返回首页"
/>
</view>
</view>
<!-- Logo -->
<!-- <image class="logo" src="/static/logo.png" mode="aspectFit"></image> -->
<!-- 欢迎语 -->
<text class="welcome-text">欢迎来到DeepChart</text>
<!-- 邮箱/手机号切换 -->
<view class="switch-container">
<text
class="switch-item"
:class="{ active: switchType === 'Email' }"
@click="switchEmail"
>邮箱</text
>
<text
class="switch-item"
:class="{ active: switchType === 'Phone' }"
@click="switchPhone"
>手机号</text
>
</view>
<!-- 输入框 -->
<view class="input-container">
<view v-if="switchType === 'Email'">
<!-- 修改邮箱输入框容器将图标包含在内 -->
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Mail.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入邮箱"
v-model="email"
/>
<view>
<button
class="send-code-btn-email"
:disabled="isCodeBtnDisabled"
:class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
@click="sendCode"
>
<text
class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text
>
</button>
</view>
</view>
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Text-recognition.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入验证码"
v-model="verifyCode"
/>
</view>
</view>
<view v-if="switchType === 'Phone'" class="phone-input-container">
<view class="country-code-selector" @click="showCountryPicker">
<image
class="country-flag-img"
src="../../../static/icons/Iphone.png"
mode="aspectFit"
></image>
<text class="country-code">{{ selectedCountry.code }}</text>
<!-- <text class="arrow-down"></text> -->
</view>
<input
class="input-field phone-input"
type="number"
placeholder="输入手机号"
v-model="phone"
@input="onPhoneInput"
/>
<view>
<button
class="send-code-btn"
:disabled="isCodeBtnDisabled"
:class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
@click="sendCode"
>
<text
class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text
>
</button>
</view>
</view>
<view v-if="switchType === 'Phone'" class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Text-recognition.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入验证码"
v-model="verifyCode"
/>
</view>
</view>
<!-- 用户协议 -->
<view @click="changeCheckbox" class="agreement-container-one">
<image class="checkbox" :src="checkboxUrl"></image>
<text class="agreement-text-one"
>接受 <text class="link" @click="openAgreement">用户协议</text>
<text class="link" @click="openPrivacy">隐私政策</text></text
>
</view>
<!-- 注册按钮 -->
<button class="register-btn" @click="register">注册</button>
<!-- 或者 -->
<text class="or-text" @click="goToLogin">已有账号
<text class="link">登录</text>
</text>
<!-- 同意弹窗 -->
<uniPopup ref="agreementPopup" type="dialog">
<view class="popup-content">
<text class="popup-message"
>请阅读并同意<text @click="openAgreement" class="popup-message-link"
>服务协议</text
><text @click="openPrivacy" class="popup-message-link"
>隐私权限</text
>
</text>
<view class="button-group">
<button class="cancel-button" @click="handleCancel">
<text class="cancel-text">取消</text>
</button>
<button class="agree-button" @click="handleAgree">
<text class="agree-text">同意</text>
</button>
</view>
</view>
</uniPopup>
<footerBar class="static-footer" :type="type"></footerBar>
</view>
</template>
<script setup>
import { ref } from "vue";
//
import countryList from "../login/list";
import footerBar from "../../../components/footerBar-cn.vue";
import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
import { verificationPhone, verificationEmail } from "../login/verification";
const type = ref("member");
const email = ref("");
const password = ref("");
const phone = ref("");
const country = ref("+86");
const agreed = ref(false);
const switchType = ref("Phone"); //
const { safeAreaInsets } = uni.getSystemInfoSync();
const codeBtnText = ref("获取验证码");
const isCodeBtnDisabled = ref(false); //
const checkboxUrl = ref("../../../static/icons/Check-one-false.png");
const verifyCode = ref("");
const account = ref("");
// 使list.js
const countries = ref(
countryList.list.map((item) => ({
name: item.name,
code: `+${item.tel}`,
flag: item.flag,
short: item.short,
en: item.en,
}))
);
//
const selectedCountry = ref(
countries.value.find((country) => country.short === "CN") ||
countries.value[0]
);
//
function showCountryPicker() {
uni.showActionSheet({
itemList: countries.value.map(
(country) => `${country.name} ${country.code}`
),
success: function (res) {
selectedCountry.value = countries.value[res.tapIndex];
},
});
}
function goToIndex() {
//
uni.navigateTo({
url: "/pages/start/index/index",
});
}
function switchEmail() {
//
switchType.value = "Email";
verifyCode.value = "";
}
function switchPhone() {
//
switchType.value = "Phone";
verifyCode.value = "";
}
// function register() {
// if (switchType.value === "Email") {
// //
// if (!email.value) {
// uni.showToast({
// title: "",
// icon: "none",
// });
// return;
// }
// //
// console.log(":", email.value);
// }
// if (switchType.value === "Phone") {
// //
// if (!phone.value) {
// uni.showToast({
// title: "",
// icon: "none",
// });
// return;
// }
// //
// console.log(":", phone.value);
// }
// }
function register() {
if (!basicVerification()) {
return;
}
}
//
function basicVerification() {
if (switchType.value === "User") {
if (!deepChartID.value) {
uni.showToast({
title: "请输入用户名",
icon: "none",
});
return false;
}
if (!password.value) {
uni.showToast({
title: "请输入密码",
icon: "none",
});
return false;
}
}
if (switchType.value === "Phone") {
//
if (!phone.value) {
uni.showToast({
title: "请输入手机号码",
icon: "none",
});
return false;
}
const phoneAll = `${country.value}${phone.value}`;
console.log("完整手机号" + phoneAll);
if (!validatePhoneNumber(country.value, phone.value)) {
return false;
}
if (!verifyCode.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return false;
}
}
if (switchType.value === "Email") {
//
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return false;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return false;
}
if (!verifyCode.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return false;
}
}
if (!agreed.value) {
//
agreementPopup.value.open();
return;
}
return true;
}
//
function VerCodeVerfifcation() {
if (switchType.value === "Phone") {
if (!phone.value) {
uni.showToast({
title: "请输入手机号",
icon: "none",
});
return false;
}
const bool = verificationPhone(country.value, phone.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return false;
}
}
if (switchType.value === "Email") {
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return false;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return false;
}
}
return true;
}
function goToLogin() {
//
uni.navigateTo({
url: "/pages/start/login/login",
});
}
function onPhoneInput(e) {
//
const value = e.detail.value;
// 使 isNaN
if (isNaN(value)) {
phone.value = "";
} else {
phone.value = value;
}
}
function sendCode() {
if (!VerCodeVerfifcation()) {
return ;
}
//
if (isCodeBtnDisabled.value) return;
//
isCodeBtnDisabled.value = true;
codeBtnText.value = "重新发送";
let time = 6;
const timer = setInterval(() => {
time--;
codeBtnText.value = "重新发送 " + time + "s";
if (time <= 0) {
clearInterval(timer);
codeBtnText.value = "重新发送";
//
isCodeBtnDisabled.value = false;
}
}, 1000);
return;
}
function openAgreement() {
//
console.log("打开用户协议");
uni.navigateTo({
url: "/pages/start/agreement/agreement",
});
}
function openPrivacy() {
//
console.log("打开隐私政策");
uni.navigateTo({
url: "/pages/start/privacy/privacy",
});
}
function changeCheckbox() {
agreed.value = !agreed.value;
checkboxUrl.value = agreed.value
? "../../../static/icons/Check-one-true.png"
: "../../../static/icons/Check-one-false.png";
}
//
function validatePhoneNumber(countryCode, phoneNumber) {
//
if (!phoneNumber || phoneNumber.trim() === "") {
uni.showToast({
title: "手机号不能为空",
icon: "none",
});
return false;
}
const bool = verificationPhone(countryCode, phoneNumber);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return false;
}
// +715
const cleanNumber = phoneNumber.replace(/^\+/, "");
if (cleanNumber.length < 7 || cleanNumber.length > 15) {
uni.showToast({
title: "手机号长度不正确",
icon: "none",
});
return false;
}
return true;
}
//
const agreementPopup = ref(null);
//
function handleAgree() {
//
agreementPopup.value.close();
//
agreed.value = true;
checkboxUrl.value = "../../../static/icons/Check-one-true.png";
//
}
//
function handleCancel() {
//
agreementPopup.value.close();
}
</script>
<style scoped>
.login-registration-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 70rpx;
height: 100vh;
background-color: #ffffff;
}
/* 自定义导航栏样式 */
.custom-navbar {
position: absolute;
top: 0;
left: 0;
/* z-index: 999; */
width: 90%;
height: 80rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 40rpx;
margin-bottom: 20rpx;
}
.nav-left,
.nav-right {
flex: 1;
}
.nav-right {
display: flex;
justify-content: flex-end;
}
.icons {
margin: 20rpx;
width: 40rpx;
height: 40rpx;
/* margin-right: 10rpx; */
}
.back-btn,
.headphone-btn {
font-size: 36rpx;
font-weight: bold;
color: #333333;
padding: 10rpx;
}
.logo {
width: 120rpx;
height: 120rpx;
margin-bottom: 60rpx;
border-radius: 20%;
}
.welcome-text {
font-size: 48rpx;
font-weight: bold;
color: #333333;
margin-bottom: 60rpx;
/* text-align: left; */
/* align-self: flex-start; */
}
.switch-container {
display: flex;
margin-bottom: 40rpx;
align-self: flex-start;
}
.switch-item {
font-size: 28rpx;
color: #999999;
padding: 10rpx 20rpx;
position: relative;
}
.switch-item::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
/* 控制边框宽度 */
height: 2rpx;
background-color: transparent;
}
.switch-item.active {
color: #333333;
font-weight: 700;
}
.switch-item.active::after {
content: "";
position: absolute;
top: 60rpx;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 30%;
/* 控制边框宽度 */
height: 7rpx;
background-color: #333333;
}
.input-container {
width: 100%;
}
/* 添加图标输入框样式 */
.input-with-icon {
display: flex;
align-items: center;
width: 100%;
height: 80rpx;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 20rpx;
}
.input-icon {
width: 40rpx;
height: 40rpx;
margin: 0 20rpx;
}
.input-field {
flex: 1;
height: 80rpx;
padding: 15rpx 0;
font-size: 28rpx;
color: #333333;
border: none;
background-color: transparent;
}
.phone-input-container {
display: flex;
align-items: center;
width: 95.8%;
height: 80rpx;
/* border-radius: 20rpx; */
/* border: 2rpx solid #e5e5e5; */
/* background-color: #f5f5f5; */
padding: 0 10rpx;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 20rpx;
}
.country-code-selector {
display: flex;
align-items: center;
padding: 0 10rpx;
padding-bottom: 1rpx;
height: 100%;
/* border-right: 2rpx solid #e5e5e5; */
/* background-color: #f5f5f5; */
border-radius: 20rpx 0 0 20rpx;
}
.country-code {
font-size: 28rpx;
color: #333333;
margin-right: 10rpx;
}
.country-flag-img {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.arrow-down {
font-size: 20rpx;
color: #999999;
}
.phone-input {
flex: 1;
width: auto;
height: 100%;
border: none;
background-color: transparent;
padding: 0 0rpx;
}
.send-code-btn {
width: 200rpx;
height: 60rpx;
display: inline-flex;
padding: 0rpx 10rpx;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 4px;
background: #000;
}
.send-code-btn-email {
width: 200rpx;
height: 60rpx;
display: inline-flex;
padding: 0rpx 10rpx;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 4px;
background: #000;
margin-right: 15rpx;
}
.send-code-btn-disabled {
background: #e6e6e6;
/* 禁用状态下的灰色背景 */
}
.send-code-btn-disabled-text {
color: #999999 !important;
}
.send-code-text {
color: #fff;
font-size: 28rpx;
}
.agreement-container-one {
display: flex;
align-items: center;
align-self: flex-start;
margin-bottom: 80rpx;
}
.agreement-container {
display: flex;
align-items: center;
margin-bottom: 40rpx;
margin-top: -75.5rpx;
align-self: flex-start;
}
.checkbox {
width: 30rpx;
height: 30rpx;
margin-left: 20rpx;
/* flex: content; */
}
.agreement-text-one {
font-size: 22rpx;
color: #666666;
text-align: center;
margin-left: 10rpx;
}
.agreement-text {
margin-left: 20rpx;
font-size: 24rpx;
color: #666666;
}
.link {
color: #333333;
font-weight: bold;
text-decoration: underline;
}
.register-btn {
width: 100%;
height: 80rpx;
background-color: #000000;
color: white;
font-size: 32rpx;
font-weight: bold;
border-radius: 40rpx;
margin-bottom: 40rpx;
}
.or-text {
flex-direction: column;
font-size: 24rpx;
color: #999999;
margin-top: 330rpx;
margin-bottom: -22rpx;
}
.third-party-login {
width: 100%;
margin-bottom: 60rpx;
}
.third-party-text {
color: #ffffff;
font-weight: bold;
white-space: pre;
}
.third-party-btn {
width: 100%;
height: 80rpx;
background-color: rgb(0, 0, 0);
border: 2rpx solid #e5e5e5;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
font-size: 28rpx;
color: #333333;
}
.google-icon,
.apple-icon {
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
}
.existing-account {
display: flex;
align-items: center;
}
.account-text {
font-size: 24rpx;
color: #666666;
}
.login-link {
font-size: 24rpx;
font-weight: bold;
color: #333333;
margin-left: 10rpx;
text-decoration: underline;
}
.static-footer {
position: fixed;
bottom: 0;
}
/* 弹窗样式 */
.popup-content {
background-color: #ffffff;
padding: 40rpx;
text-align: center;
border-radius: 10rpx;
width: 550rpx;
}
.popup-message {
font-size: 28rpx;
color: #000000;
margin-bottom: 60rpx;
margin-top: 20rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
font-weight: 300;
}
.popup-message-link {
font-weight: 700;
}
.button-group {
display: flex;
justify-content: space-around;
}
.agree-button {
width: 160rpx;
height: 56rpx;
background-color: #000000;
border-radius: 40rpx;
display: flex; /* 添加flex布局 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.agree-text {
color: #ffffff;
font-size: 34rpx;
/* 添加垂直居中相关样式 */
display: flex;
align-items: center;
justify-content: center;
line-height: 1; /* 确保文字垂直居中 */
}
.cancel-button {
width: 160rpx;
height: 56rpx;
background-color: #e5e5e5;
border-radius: 40rpx;
display: flex; /* 添加flex布局 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.cancel-text {
color: #333333;
font-size: 34rpx;
/* 添加垂直居中相关样式 */
display: flex;
align-items: center;
justify-content: center;
line-height: 1; /* 确保文字垂直居中 */
}
</style>

1341
pages/start/Registration/list.js
File diff suppressed because it is too large
View File

13
pages/start/agreement/agreement.vue

@ -0,0 +1,13 @@
<template>
<view>
用户协议
</view>
</template>
<script setup>
</script>
<style>
</style>

55
pages/start/index/index.vue

@ -0,0 +1,55 @@
<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
<text class="title" @click="showLoginPrompt">{{ title }}</text>
</view>
<LoginPrompt ref="loginPrompt"></LoginPrompt>
<button @click="toDeepMate">deepMate</button>
</view>
</template>
<script setup>
import { ref } from "vue";
const title = ref("请先登录");
const loginPrompt = ref(null);
function showLoginPrompt() {
loginPrompt.value.show();
}
function toDeepMate() {
uni.navigateTo({
url: '/pages/deepMate/deepMate'
})
}
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}
.text-area {
display: flex;
justify-content: center;
}
.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>

1341
pages/start/login/list.js
File diff suppressed because it is too large
View File

1111
pages/start/login/login.vue
File diff suppressed because it is too large
View File

69
pages/start/login/verification.js

@ -0,0 +1,69 @@
function verificationPhone(countryCode,phoneNumber) {
switch (countryCode) {
case '+86':
return verificationChina(phoneNumber);
case '+1':
return verificationAmerica(phoneNumber);
case '+65':
return verificationSingapore(phoneNumber);
case '+60':
return verificationMalaysia(phoneNumber);
case '+66':
return verificationThailand(phoneNumber);
case '+852':
return verificationHongKong(phoneNumber);
case '+84':
return verificationVietnam(phoneNumber);
default:
return true;
}
}
function verificationChina(phoneNumber){
const phoneRegex = /^1[3-9]\d{9}$/;
return phoneRegex.test(phoneNumber);
}
function verificationAmerica(phoneNumber){
const phoneRegex = /^[2-9]\d{2}[- ]?\d{4}$/;
return phoneRegex.test(phoneNumber);
}
function verificationSingapore(phoneNumber){
const phoneRegex = /^[89]\d{7}$/;
return phoneRegex.test(phoneNumber);
}
function verificationMalaysia(phoneNumber){
const phoneRegex = /^01\d{8}$/;
return phoneRegex.test(phoneNumber);
}
function verificationHongKong(phoneNumber){
const phoneRegex = /^0[896]\d{8}$/;
return phoneRegex.test(phoneNumber);
}
function verificationThailand(phoneNumber){
const phoneRegex = /^[5-9]\d{7}$/;
return phoneRegex.test(phoneNumber);
}
function verificationVietnam(phoneNumber){
const phoneRegex = /^(0)?[3-9]\d{8}$/;
return phoneRegex.test(phoneNumber);
}
function verificationEmail(email) {
const emailRegex = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/;
return emailRegex.test(email);
}
export {verificationPhone,verificationEmail}

13
pages/start/privacy/privacy.vue

@ -0,0 +1,13 @@
<template>
<view>
隐私政策
</view>
</template>
<script setup>
</script>
<style>
</style>

976
pages/start/recoverPassword/recoverPassword.vue

@ -0,0 +1,976 @@
<template>
<view class="login-registration-container">
<!-- 自定义导航栏 -->
<view
class="custom-navbar"
:style="{ paddingTop: safeAreaInsets?.top + 'px' }"
>
<view class="nav-left">
<image
class="icons"
@click="goToBack"
src="../../../static/icons/back.png"
alt="返回首页"
/>
</view>
<view class="nav-right">
<image
class="icons"
src="../../../static/icons/Headset.png"
alt="联系客服"
/>
</view>
</view>
<!-- Logo -->
<!-- <image class="logo" src="/static/logo.png" mode="aspectFit"></image> -->
<!-- 欢迎语 -->
<text class="welcome-text">找回密码</text>
<!-- 邮箱/手机号切换 -->
<view v-if="!isRecovering" class="switch-container">
<text
class="switch-item"
:class="{ active: switchType === 'Email' }"
@click="switchEmail"
>邮箱</text
>
<text
class="switch-item"
:class="{ active: switchType === 'Phone' }"
@click="switchPhone"
>手机号</text
>
</view>
<view v-else class="switch-container-occupy"> </view>
<!-- 输入框 -->
<view v-if="isRecovering" class="input-container">
<view >
<!-- 修改邮箱输入框容器将图标包含在内 -->
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Unlock.png"
alt=""
/>
<input
class="input-field"
:type="newPasswordLookFirst ? 'text' : 'password'"
placeholder="输入新密码"
v-model="newPasswordFirst"
/>
<image
class="input-icon-eye"
@click="newPasswordLookFirst = !newPasswordLookFirst"
:src="
!newPasswordLookFirst
? '../../../static/icons/unlook.png'
: '../../../static/icons/look.png'
"
alt=""
/>
</view>
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Unlock.png"
alt=""
/>
<input
class="input-field"
:type="newPasswordLookSecond ? 'text' : 'password'"
placeholder="再次确认"
v-model="newPasswordSecond"
/>
<image
class="input-icon-eye"
@click="newPasswordLookSecond = !newPasswordLookSecond"
:src="
!newPasswordLookSecond
? '../../../static/icons/unlook.png'
: '../../../static/icons/look.png'
"
alt=""
/>
</view>
</view>
</view>
<view v-else class="input-container">
<view v-if="switchType === 'Email'">
<!-- 修改邮箱输入框容器将图标包含在内 -->
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Mail.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入邮箱"
v-model="email"
/>
<view>
<button
class="send-code-btn-email"
:disabled="isCodeBtnDisabled"
:class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
@click="sendCode"
>
<text
class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text
>
</button>
</view>
</view>
<view class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Text-recognition.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入验证码"
v-model="verifyCode"
/>
</view>
</view>
<view v-if="switchType === 'Phone'" class="phone-input-container">
<view class="country-code-selector" @click="showCountryPicker">
<image
class="country-flag-img"
src="../../../static/icons/Iphone.png"
mode="aspectFit"
></image>
<text class="country-code">{{ selectedCountry.code }}</text>
<!-- <text class="arrow-down"></text> -->
</view>
<input
class="input-field phone-input"
type="number"
placeholder="输入手机号"
v-model="phone"
@input="onPhoneInput"
/>
<view>
<button
class="send-code-btn"
:disabled="isCodeBtnDisabled"
:class="{ 'send-code-btn-disabled': isCodeBtnDisabled }"
@click="sendCode"
>
<text
class="send-code-text"
:class="{ 'send-code-btn-disabled-text': isCodeBtnDisabled }"
>{{ codeBtnText }}</text
>
</button>
</view>
</view>
<view v-if="switchType === 'Phone'" class="input-with-icon">
<image
class="input-icon"
src="../../../static/icons/Text-recognition.png"
alt=""
/>
<input
class="input-field"
type="text"
placeholder="请输入验证码"
v-model="verifyCode"
/>
</view>
</view>
<!-- 用户协议 -->
<view @click="changeCheckbox" class="agreement-container-one">
<text
class="agreement-text-one"
:style="!isRecovering ? 'visibility: hidden' : 'visibility: visible'"
>
密码最少8位数
</text>
</view>
<!-- 注册按钮 -->
<button class="register-btn" @click="register">
{{ isRecovering ? "确认" : "下一步" }}
</button>
<!-- 或者 -->
<text class="or-text-one" @click="goToRegistration"
>如果您还没有账号点击注册
<image class="to-icon" src="../../../static/icons/To.png"></image>
</text>
<!-- 或者 -->
<text class="or-text" @click="goToLogin">已有账号登录 </text>
<!-- 同意弹窗 -->
<uniPopup ref="agreementPopup" type="dialog">
<view class="popup-content">
<text class="popup-title">同意并继续</text>
<text class="popup-message">请阅读并同意服务协议和隐私权限</text>
<button class="agree-button" @click="handleAgree">
<text class="agree-text">同意</text>
</button>
</view>
</uniPopup>
<footerBar class="static-footer" :type="type"></footerBar>
</view>
</template>
<script setup>
import { ref } from "vue";
//
import countryList from "../login/list";
import footerBar from "../../../components/footerBar-cn.vue";
import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
import { verificationPhone, verificationEmail } from "../login/verification";
const type = ref("member");
const email = ref("");
const password = ref("");
const newPasswordFirst = ref("");
const newPasswordSecond = ref("");
const phone = ref("");
const country = ref("+86");
const agreed = ref(false);
const switchType = ref("Phone"); //
const { safeAreaInsets } = uni.getSystemInfoSync();
const codeBtnText = ref("获取验证码");
const isCodeBtnDisabled = ref(false); //
const checkboxUrl = ref("../../../static/icons/Check-one-false.png");
const verifyCode = ref("");
const isRecovering = ref(false);
const newPasswordLookFirst = ref(false);
const newPasswordLookSecond = ref(false);
// 使list.js
const countries = ref(
countryList.list.map((item) => ({
name: item.name,
code: `+${item.tel}`,
flag: item.flag,
short: item.short,
en: item.en,
}))
);
//
const selectedCountry = ref(
countries.value.find((country) => country.short === "CN") ||
countries.value[0]
);
//
function showCountryPicker() {
uni.showActionSheet({
itemList: countries.value.map(
(country) => `${country.name} ${country.code}`
),
success: function (res) {
selectedCountry.value = countries.value[res.tapIndex];
},
});
}
function goToBack() {
//
uni.navigateBack(-1);
}
function switchEmail() {
//
switchType.value = "Email";
verifyCode.value = "";
}
function switchPhone() {
//
switchType.value = "Phone";
verifyCode.value = "";
}
function register() {
if (isRecovering.value) {
if (!newPasswordFirst.value || !newPasswordSecond.value) {
uni.showToast({
title: "密码不能为空",
icon: "none",
});
return;
}
if (newPasswordFirst.value !== newPasswordSecond.value) {
uni.showToast({
title: "前后密码不一致",
icon: "none",
});
return;
}
//
return;
}
if (switchType.value === "Phone") {
//
if (!phone.value) {
uni.showToast({
title: "请输入手机号码",
icon: "none",
});
return;
}
console.log("123");
const phoneAll = `${country.value}${phone.value}`;
console.log("完整手机号" + phoneAll);
if (!validatePhoneNumber(country.value, phone.value)) {
return;
}
if (!verifyCode.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return;
}
}
if (switchType.value === "Email") {
//
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return;
}
if (!verifyCode.value) {
uni.showToast({
title: "请输入验证码",
icon: "none",
});
return;
}
//
console.log("登录:", email.value);
}
isRecovering.value = !isRecovering.value;
//
// uni.showToast({
// title: "",
// icon: "success",
// });
}
function goToLogin() {
//
uni.navigateTo({
url: "/pages/start/login/login",
});
}
function onPhoneInput(e) {
//
const value = e.detail.value;
// 使 isNaN
if (isNaN(value)) {
phone.value = "";
} else {
phone.value = value;
}
}
//
function VerCodeVerfifcation() {
if (switchType.value === "Phone") {
if (!phone.value) {
uni.showToast({
title: "请输入手机号",
icon: "none",
});
return false;
}
const bool = verificationPhone(country.value, phone.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return false;
}
}
if (switchType.value === "Email") {
if (!email.value) {
uni.showToast({
title: "请输入邮箱地址",
icon: "none",
});
return false;
}
const bool = verificationEmail(email.value);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "邮箱格式不正确",
icon: "none",
});
return false;
}
}
return true;
}
//
function sendCode() {
if (!VerCodeVerfifcation()) {
return;
}
//
if (isCodeBtnDisabled.value) return;
//
isCodeBtnDisabled.value = true;
codeBtnText.value = "重新发送";
let time = 6;
const timer = setInterval(() => {
time--;
codeBtnText.value = "重新发送 " + time + "s";
if (time <= 0) {
clearInterval(timer);
codeBtnText.value = "重新发送";
//
isCodeBtnDisabled.value = false;
}
}, 1000);
return;
}
function openAgreement() {
//
console.log("打开用户协议");
uni.navigateTo({
url: "/pages/start/agreement/agreement",
});
}
function openPrivacy() {
//
console.log("打开隐私政策");
uni.navigateTo({
url: "/pages/start/privacy/privacy",
});
}
function changeCheckbox() {
agreed.value = !agreed.value;
checkboxUrl.value = agreed.value
? "../../../static/icons/Check-one-true.png"
: "../../../static/icons/Check-one-false.png";
}
//
function validatePhoneNumber(countryCode, phoneNumber) {
//
if (!phoneNumber || phoneNumber.trim() === "") {
uni.showToast({
title: "手机号不能为空",
icon: "none",
});
return false;
}
const bool = verificationPhone(countryCode, phoneNumber);
console.log("验证是否成功", bool);
//
if (!bool) {
uni.showToast({
title: "手机号格式不正确",
icon: "none",
});
return false;
}
// +715
const cleanNumber = phoneNumber.replace(/^\+/, "");
if (cleanNumber.length < 7 || cleanNumber.length > 15) {
uni.showToast({
title: "手机号长度不正确",
icon: "none",
});
return false;
}
return true;
}
//
const agreementPopup = ref(null);
//
function handleAgree() {
//
agreementPopup.value.close();
//
agreed.value = true;
checkboxUrl.value = "../../../static/icons/Check-one-true.png";
//
}
</script>
<style scoped>
.login-registration-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 70rpx;
height: 100vh;
background-color: #ffffff;
}
/* 自定义导航栏样式 */
.custom-navbar {
position: absolute;
top: 0;
left: 0;
/* z-index: 999; */
width: 90%;
height: 80rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 40rpx;
margin-bottom: 20rpx;
}
.nav-left,
.nav-right {
flex: 1;
}
.nav-right {
display: flex;
justify-content: flex-end;
}
.nav-left {
display: flex;
justify-content: flex-start;
}
.icons {
margin: 20rpx;
width: 40rpx;
height: 40rpx;
/* margin-right: 10rpx; */
}
.back-btn,
.headphone-btn {
font-size: 36rpx;
font-weight: bold;
color: #333333;
padding: 10rpx;
}
.logo {
width: 120rpx;
height: 120rpx;
margin-bottom: 60rpx;
border-radius: 20%;
}
.welcome-text {
font-size: 48rpx;
font-weight: bold;
color: #333333;
margin-bottom: 60rpx;
/* text-align: left; */
/* align-self: flex-start; */
}
.switch-container {
display: flex;
margin-bottom: 40rpx;
align-self: flex-start;
}
.switch-item {
font-size: 28rpx;
color: #999999;
padding: 10rpx 20rpx;
position: relative;
}
.switch-item::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 60%;
/* 控制边框宽度 */
height: 2rpx;
background-color: transparent;
}
.switch-item.active {
color: #333333;
font-weight: 700;
}
.switch-item.active::after {
content: "";
position: absolute;
top: 60rpx;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 30%;
/* 控制边框宽度 */
height: 7rpx;
background-color: #333333;
}
.input-container {
width: 100%;
}
/* 添加图标输入框样式 */
.input-with-icon {
display: flex;
align-items: center;
width: 100%;
height: 80rpx;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 20rpx;
}
.input-icon {
width: 40rpx;
height: 40rpx;
margin: 0 20rpx;
}
.input-icon-eye {
width: 40rpx;
height: 20rpx;
margin: 0 20rpx;
}
.input-field {
flex: 1;
height: 80rpx;
padding: 15rpx 0;
font-size: 28rpx;
color: #333333;
border: none;
background-color: transparent;
}
.phone-input-container {
display: flex;
align-items: center;
width: 95.8%;
height: 80rpx;
/* border-radius: 20rpx; */
/* border: 2rpx solid #e5e5e5; */
/* background-color: #f5f5f5; */
padding: 0 10rpx;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 20rpx;
}
.country-code-selector {
display: flex;
align-items: center;
padding: 0 10rpx;
padding-bottom: 1rpx;
height: 100%;
/* border-right: 2rpx solid #e5e5e5; */
/* background-color: #f5f5f5; */
border-radius: 20rpx 0 0 20rpx;
}
.country-code {
font-size: 28rpx;
color: #333333;
margin-right: 10rpx;
}
.country-flag-img {
width: 40rpx;
height: 40rpx;
margin-right: 10rpx;
}
.arrow-down {
font-size: 20rpx;
color: #999999;
}
.phone-input {
flex: 1;
width: auto;
height: 100%;
border: none;
background-color: transparent;
padding: 0 0rpx;
}
.send-code-btn {
width: 200rpx;
height: 60rpx;
display: inline-flex;
padding: 0rpx 10rpx;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 4px;
background: #000;
}
.send-code-btn-email {
width: 200rpx;
height: 60rpx;
display: inline-flex;
padding: 0rpx 10rpx;
justify-content: center;
align-items: center;
gap: 10px;
border-radius: 4px;
background: #000;
margin-right: 15rpx;
}
.send-code-btn-disabled {
background: #e6e6e6;
/* 禁用状态下的灰色背景 */
}
.send-code-btn-disabled-text {
color: #999999 !important;
}
.send-code-text {
color: #fff;
font-size: 28rpx;
}
.agreement-container-one {
display: flex;
align-items: center;
align-self: flex-start;
margin-bottom: 80rpx;
}
.agreement-container {
display: flex;
align-items: center;
margin-bottom: 40rpx;
margin-top: -75.5rpx;
align-self: flex-start;
}
.checkbox {
width: 30rpx;
height: 30rpx;
margin-left: 20rpx;
/* flex: content; */
}
.agreement-text-one {
font-size: 22rpx;
color: #666666;
text-align: center;
margin-left: 10rpx;
}
.agreement-text {
margin-left: 20rpx;
font-size: 24rpx;
color: #666666;
}
.link {
color: #333333;
font-weight: bold;
text-decoration: underline;
}
.register-btn {
width: 100%;
height: 80rpx;
background-color: #000000;
color: white;
font-size: 32rpx;
font-weight: bold;
border-radius: 40rpx;
margin-bottom: 40rpx;
}
.or-text {
flex-direction: column;
font-size: 24rpx;
color: #999999;
margin-top: 294rpx;
margin-bottom: -22rpx;
}
.to-icon {
width: 10rpx;
height: 16rpx;
}
.or-text-one {
flex-direction: column;
font-size: 24rpx;
color: #999999;
}
.third-party-login {
width: 100%;
margin-bottom: 60rpx;
}
.third-party-text {
color: #ffffff;
font-weight: bold;
white-space: pre;
}
.third-party-btn {
width: 100%;
height: 80rpx;
background-color: rgb(0, 0, 0);
border: 2rpx solid #e5e5e5;
border-radius: 40rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
font-size: 28rpx;
color: #333333;
}
.google-icon,
.apple-icon {
width: 60rpx;
height: 60rpx;
margin-right: 20rpx;
}
.existing-account {
display: flex;
align-items: center;
}
.account-text {
font-size: 24rpx;
color: #666666;
}
.login-link {
font-size: 24rpx;
font-weight: bold;
color: #333333;
margin-left: 10rpx;
text-decoration: underline;
}
.static-footer {
position: fixed;
bottom: 0;
}
/* 弹窗样式 */
.popup-content {
background-color: #ffffff;
padding: 40rpx;
text-align: center;
border-radius: 10rpx;
width: 550rpx;
}
.popup-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 80rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.popup-message {
font-size: 28rpx;
color: #000000;
margin-bottom: 80rpx;
text-align: center; /* 水平居中 */
display: flex; /* 使用flex布局 */
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
.agree-button {
width: 300rpx;
height: 80rpx;
background-color: #000000;
border-radius: 40rpx;
display: flex; /* 添加flex布局 */
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
}
.agree-text {
color: #ffffff;
font-size: 34rpx;
/* 添加垂直居中相关样式 */
display: flex;
align-items: center;
justify-content: center;
line-height: 1; /* 确保文字垂直居中 */
}
.switch-container-occupy {
margin-top: 100rpx;
}
</style>

175
pages/start/select/select.vue

@ -0,0 +1,175 @@
<template>
<view class="login-container">
<!-- 顶部标题 -->
<view class="title-section">
<text class="main-title">DeepChart</text>
</view>
<view class="subtitle-section">
<text class="subtitle">您的股市随身顾问</text>
</view>
<!-- 手机卡片样式 -->
<view class="phone-card"> </view>
<!-- 登录注册按钮 -->
<view class="button-group">
<button class="login-button" @click="toLogin">登录</button>
<button class="register-button" @click="toRegistration">注册</button>
</view>
<footerBar class="static-footer" :type="type"></footerBar>
</view>
</template>
<script setup>
import footerBar from '../../../components/footerBar-cn'
import { ref, reactive, toRefs, watch } from 'vue'
const type = ref('member')
function toRegistration() {
uni.navigateTo({
url: "/pages/start/Registration/Registration",
});
}
function toLogin() {
uni.navigateTo({
url: "/pages/start/login/login",
});
}
</script>
<style scoped>
.login-container {
display: flex;
flex-direction: column;
align-items: center;
/* justify-content: space-between; */
padding: 40rpx;
height: 90vh;
background-color: #ffffff;
overflow: hidden;
max-height: 100vh;
-webkit-overflow-scrolling: none;
}
.title-section {
text-align: center;
margin-top: 120rpx;
margin-bottom: 20rpx;
}
.main-title {
text-align: center;
font-size: 64rpx;
font-weight: 300;
color: #000000;
margin-bottom: 10rpx;
}
.subtitle-section {
margin-bottom: 80rpx;
}
.subtitle {
/* font-weight: bold; */
font-size: 32rpx;
color: #333333;
}
.phone-card {
background-image: url("/static/select.png");
background-repeat: no-repeat;
background-size: contain;
background-position: center;
/* background-position: center; */
/* min-width: 300rpx; */
width: 420rpx;
height: 786rpx;
border-radius: 50rpx;
padding: 40rpx;
/* box-shadow: 0 20rpx 40rpx rgba(0, 0, 0, 0.3); */
position: relative;
overflow: hidden;
}
.button-group {
display: flex;
gap: 40rpx;
margin: 80rpx 0;
width: 100%;
max-width: 600rpx;
}
.login-button {
flex: 1;
background-color: #f5f5f5;
color: #000000;
border-radius: 60rpx;
font-size: 32rpx;
padding: 20rpx;
}
.register-button {
flex: 1;
background-color: #000000;
color: #ffffff;
border-radius: 60rpx;
font-size: 32rpx;
padding: 20rpx;
}
.bottom-nav {
display: flex;
justify-content: space-around;
align-items: center;
width: 100%;
height: 100rpx;
background-color: #ffffff;
position: fixed;
bottom: 0;
left: 0;
border-top: 1rpx solid #e5e5e5;
}
.nav-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 10rpx;
}
.nav-item.active .nav-icon {
transform: scale(1.2);
}
.nav-icon {
width: 40rpx;
height: 40rpx;
margin-bottom: 10rpx;
}
.nav-text {
font-size: 24rpx;
color: #666666;
}
.nav-item.active .nav-text {
color: #000000;
}
.static-footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
</style>

56
pages/start/startup/startup.vue

@ -0,0 +1,56 @@
<template>
<view class="background">
<image
class="logo"
src="../../../static/icons/start-logo.png"
mode="scaleToFill"
/>
<view class="logo-text"> DeepChart </view>
</view>
</template>
<script setup>
import { onShow } from "@dcloudio/uni-app";
onShow(() => {
setTimeout(() => {
uni.redirectTo({
url: "/pages/start/select/select",
animationType: "slide-in-right",
animationDuration: 1000,
});
}, 1500);
});
</script>
<style>
.background {
background: linear-gradient(180deg, #FB6967, #FB6967);
width: 100vw;
height: 100vh;
}
.logo-text {
display: flex;
justify-content: center;
align-items: center;
color: white;
font-weight: bold;
font-size: 24px;
position: absolute;
bottom: 5%;
left: 50%;
transform: translateX(-50%);
}
.logo{
width: 320rpx;
height: 200rpx;
position: absolute;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>

23
server/deepchart.json

@ -0,0 +1,23 @@
{
"intent":{
"code": 200,
"message": "操作成功",
"data": {
"code": "1A0001",
"market": "cn",
"name": "上证指数",
"refuse": "",
"recordId": 15,
"parentId": 14,
"stockId": 25,
"language": "cn",
"debug_url": "https://www.coze.cn/work_flow?execute_id=7564771475955515444&space_id=7564250621483040822&workflow_id=7564368306322292788&execute_mode=2"
}
},
"stocks":{"code":"200","cftl":"当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线","date":"更新时间: 24/10/2025","debug_url":"https://www.coze.cn/work_flow?execute_id=7565080703726846004&space_id=7564250621483040822&workflow_id=7564596757864071195&execute_mode=2","gfzl":"该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。","hxjzpg":"(1)牛股评级:★★☆☆☆\n(2)暴涨概率:40%\n(3)风险评估:非常安全\n(4)黄金价域:258.984~266.753\n(5)核心证据链\n 资金共识:当日多方资金流入\n 趋势动能:该股中长期处于上升趋势,短期处于强势状态。","kongjian":"预测低一值255.468,预测高一值257.692,预测低二值255.156,预测高二值255.807",
"markdown":" \n# <font style=\" line-height: 1.5 \" color=\"#1890ff\">Alphabet Inc.全景作战报告</font>\n## 📊 股票分析报告\n### 📈 股票基本信息\n- **股票名称**: <font color=\"#52c41a\">Alphabet Inc.</font>\n- **股票代码**: <font color=\"#1890ff\">GOOGL</font>\n- **当前价格**: <font color=\"#ff4d4f\">259.920</font>\n- **更新时间**: 2025年10月24日\n- **时间节点**: 今日无变盘点\n\n### 🎯 核心价值评估\n- **安全边际**: <font color=\"#13c2c2\">164.424 ~ </font>\n- **黄金价域**: <font color=\"#faad14\">258.984 ~ 266.753</font>\n- **核心证据链**:\n - 🟢 **资金共识**: 当日多方资金<font color=\"#52c41a\">流入</font>\n - 🔥 **趋势动能**: 该股中长期处于<b><font color='#FF0000'>上升趋势</font></b>,短期处于<b><font color='#FF0000'>强势状态</font></b>。\n\n### 🕵️ 主力作战分析\n- **主力行为**:\n 1. 📊 该股庄家中长期筹码成本价格为 207.497,短期资金成本价格为 239.503。该股筹码分散,当日筹码成本价格为 254.335。\n 2. 🔍 近日没有出现主力集中吸筹。\n 3. 📈 近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。\n\n### 📊 技术分析\n- **空间维度**:\n - 📉 预测低一值: <font color=\"#13c2c2\">255.468</font>\n - 📈 预测高一值: <font color=\"#ff4d4f\">257.692</font>\n - 📉 预测低二值: <font color=\"#13c2c2\">255.156</font>\n - 📈 预测高二值: <font color=\"#ff4d4f\">255.807</font>\n- **能量分析**: <font color=\"#722ed1\">AI智能均线多头排列,当前卖盘小于买盘</font>\n\n### ⚡ 综合作战分析\n- **触发条件**: <font color=\"#fa8c16\">当前股票处于安全区,牵牛绳为红色,出现蓝色推进K线</font>\n- **攻防指令**: <font color=\"#eb2f96\">该股整体趋势相对较强,个股正处于推进上涨的关键阶段。若当前持有该股票,建议继续持有,进行持续跟踪。若当前无该股票,建议持续跟踪,等待适当时机再进行介入。</font>\n\n---\n<font color=\"#8c8c8c\">*该内容由AI生成,仅供参考,投资有风险,请注意甄别。*</font>\n ","message":"","name":"股票名称: Alphabet Inc.(GOOGL)","nengliang":"AI智能均线多头排列,当前卖盘小于买盘","price":"当前价格: 259.920","shijian":"今日无变盘点","zhuli1":"(1)该股庄家中长期筹码成本价格为 207.497,短期资金成本价格为 239.503。该股筹码分散,当日筹码成本价格为 254.335。","zhuli2":"(2)近日没有出现主力集中吸筹。","zhuli3":"(3)近期主力持仓比例大于散户持仓比例。 当日主力持仓增加。 当日散户持仓减少。"}
}

131
server/login.json

@ -0,0 +1,131 @@
{
"loginSuccessByEmail": {
"code": 200,
"message": "登录成功",
"interface": "login",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"id": "123456789",
"username": "q614588746",
"email": "q614588746@163.com"
}
}
},
"loginFailureEmailNotFound": {
"code": 404,
"message": "账号不存在",
"interface": "login"
},
"loginFailureWrongCode": {
"code": 400,
"message": "验证码错误",
"interface": "login"
},
"loginSuccessByPhone": {
"code": 200,
"message": "登录成功",
"interface": "login",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"id": "987654321",
"username": "13800138000",
"phone": "13800138000"
}
}
},
"loginSuccessByPassword": {
"code": 200,
"message": "登录成功",
"interface": "login",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"id": "556677889",
"username": "testuser"
}
}
},
"sendCodeSuccess": {
"code": 200,
"message": "验证码发送成功",
"interface": "sendCode",
"data": {
"expireTime": 180
}
},
"sendCodeFailureInvalidFormat": {
"code": 400,
"message": "手机号格式错误",
"interface": "sendCode"
},
"sendCodeFailureTooFrequent": {
"code": 429,
"message": "发送频率过高,请稍后再试",
"interface": "sendCode"
},
"registerSuccess": {
"code": 200,
"message": "注册成功",
"interface": "register",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"userInfo": {
"id": "112233445",
"username": "newuser",
"email": "newuser@example.com"
}
}
},
"registerFailureEmailExist": {
"code": 400,
"message": "邮箱已被注册",
"interface": "register"
},
"registerFailurePhoneExist": {
"code": 400,
"message": "手机号已被注册",
"interface": "register"
},
"registerFailureWrongCode": {
"code": 400,
"message": "验证码错误",
"interface": "register"
},
"updatePasswordSuccess": {
"code": 200,
"message": "密码修改成功",
"interface": "updatePassword"
},
"updatePasswordFailureWrongOldPassword": {
"code": 400,
"message": "旧密码错误",
"interface": "updatePassword"
},
"updatePasswordFailureWrongCode": {
"code": 400,
"message": "验证码错误",
"interface": "updatePassword"
},
"forgotPasswordSuccessByEmail": {
"code": 200,
"message": "密码重置成功,新密码已发送至邮箱",
"interface": "forgotPassword"
},
"forgotPasswordSuccessByPhone": {
"code": 200,
"message": "密码重置成功,新密码已发送至手机",
"interface": "forgotPassword"
},
"forgotPasswordFailureAccountNotFound": {
"code": 404,
"message": "账号不存在",
"interface": "forgotPassword"
},
"forgotPasswordFailureWrongCode": {
"code": 400,
"message": "验证码错误",
"interface": "forgotPassword"
}
}

BIN
static/flag/ad.png

After

Width: 100  |  Height: 70  |  Size: 2.1 KiB

BIN
static/flag/ae.png

After

Width: 100  |  Height: 50  |  Size: 170 B

BIN
static/flag/af.png

After

Width: 100  |  Height: 67  |  Size: 2.6 KiB

BIN
static/flag/ag.png

After

Width: 100  |  Height: 67  |  Size: 2.0 KiB

BIN
static/flag/ai.png

After

Width: 100  |  Height: 50  |  Size: 1.3 KiB

BIN
static/flag/al.png

After

Width: 100  |  Height: 71  |  Size: 1.7 KiB

BIN
static/flag/am.png

After

Width: 100  |  Height: 50  |  Size: 122 B

BIN
static/flag/an.png

After

Width: 100  |  Height: 67  |  Size: 610 B

BIN
static/flag/ao.png

After

Width: 100  |  Height: 67  |  Size: 1.4 KiB

BIN
static/flag/aq.png

After

Width: 100  |  Height: 100  |  Size: 6.0 KiB

BIN
static/flag/ar.png

After

Width: 100  |  Height: 63  |  Size: 991 B

BIN
static/flag/as.png

After

Width: 100  |  Height: 50  |  Size: 2.0 KiB

BIN
static/flag/at.png

After

Width: 100  |  Height: 67  |  Size: 133 B

BIN
static/flag/au.png

After

Width: 100  |  Height: 50  |  Size: 1.1 KiB

BIN
static/flag/aw.png

After

Width: 100  |  Height: 67  |  Size: 658 B

BIN
static/flag/ax.png

After

Width: 100  |  Height: 65  |  Size: 279 B

BIN
static/flag/az.png

After

Width: 100  |  Height: 50  |  Size: 451 B

BIN
static/flag/ba.png

After

Width: 100  |  Height: 50  |  Size: 741 B

BIN
static/flag/bb.png

After

Width: 100  |  Height: 67  |  Size: 791 B

BIN
static/flag/bd.png

After

Width: 100  |  Height: 60  |  Size: 367 B

BIN
static/flag/be.png

After

Width: 100  |  Height: 87  |  Size: 168 B

BIN
static/flag/bf.png

After

Width: 100  |  Height: 67  |  Size: 560 B

BIN
static/flag/bg.png

After

Width: 100  |  Height: 60  |  Size: 106 B

BIN
static/flag/bh.png

After

Width: 100  |  Height: 60  |  Size: 303 B

BIN
static/flag/bi.png

After

Width: 100  |  Height: 60  |  Size: 1.3 KiB

BIN
static/flag/bj.png

After

Width: 100  |  Height: 67  |  Size: 169 B

BIN
static/flag/bl.png

After

Width: 100  |  Height: 67  |  Size: 6.2 KiB

BIN
static/flag/bm.png

After

Width: 100  |  Height: 50  |  Size: 2.0 KiB

BIN
static/flag/bn.png

After

Width: 100  |  Height: 50  |  Size: 2.3 KiB

BIN
static/flag/bo.png

After

Width: 100  |  Height: 68  |  Size: 1.4 KiB

BIN
static/flag/bq.png

After

Width: 100  |  Height: 67  |  Size: 159 B

BIN
static/flag/br.png

After

Width: 100  |  Height: 70  |  Size: 2.0 KiB

BIN
static/flag/bs.png

After

Width: 100  |  Height: 50  |  Size: 553 B

BIN
static/flag/bt.png

After

Width: 100  |  Height: 67  |  Size: 4.0 KiB

BIN
static/flag/bv.png

After

Width: 100  |  Height: 73  |  Size: 260 B

BIN
static/flag/bw.png

After

Width: 100  |  Height: 67  |  Size: 172 B

BIN
static/flag/by.png

After

Width: 100  |  Height: 50  |  Size: 1.4 KiB

BIN
static/flag/bz.png

After

Width: 100  |  Height: 67  |  Size: 5.6 KiB

BIN
static/flag/ca.png

After

Width: 100  |  Height: 50  |  Size: 765 B

BIN
static/flag/cc.png

After

Width: 100  |  Height: 50  |  Size: 1.3 KiB

BIN
static/flag/cd.png

After

Width: 100  |  Height: 75  |  Size: 796 B

BIN
static/flag/cf.png

After

Width: 100  |  Height: 67  |  Size: 554 B

BIN
static/flag/cg.png

After

Width: 100  |  Height: 67  |  Size: 354 B

BIN
static/flag/ch.png

After

Width: 100  |  Height: 100  |  Size: 172 B

BIN
static/flag/ci.png

After

Width: 100  |  Height: 67  |  Size: 165 B

BIN
static/flag/ck.png

After

Width: 100  |  Height: 50  |  Size: 1.9 KiB

BIN
static/flag/cl.png

After

Width: 100  |  Height: 67  |  Size: 517 B

BIN
static/flag/cm.png

After

Width: 100  |  Height: 67  |  Size: 482 B

BIN
static/flag/cn.png

After

Width: 100  |  Height: 67  |  Size: 763 B

BIN
static/flag/co.png

After

Width: 100  |  Height: 67  |  Size: 158 B

BIN
static/flag/cr.png

After

Width: 100  |  Height: 60  |  Size: 109 B

BIN
static/flag/cu.png

After

Width: 100  |  Height: 50  |  Size: 793 B

BIN
static/flag/cv.png

After

Width: 100  |  Height: 59  |  Size: 1.0 KiB

BIN
static/flag/cw.png

After

Width: 100  |  Height: 67  |  Size: 633 B

BIN
static/flag/cx.png

After

Width: 100  |  Height: 50  |  Size: 1.5 KiB

BIN
static/flag/cy.png

After

Width: 100  |  Height: 67  |  Size: 1.6 KiB

BIN
static/flag/cz.png

After

Width: 100  |  Height: 67  |  Size: 394 B

BIN
static/flag/de.png

After

Width: 100  |  Height: 60  |  Size: 106 B

BIN
static/flag/dj.png

After

Width: 100  |  Height: 67  |  Size: 1.1 KiB

BIN
static/flag/dk.png

After

Width: 100  |  Height: 76  |  Size: 200 B

BIN
static/flag/dm.png

After

Width: 100  |  Height: 50  |  Size: 1.2 KiB

BIN
static/flag/do.png

After

Width: 100  |  Height: 67  |  Size: 700 B

BIN
static/flag/dz.png

After

Width: 100  |  Height: 67  |  Size: 891 B

BIN
static/flag/ec.png

After

Width: 100  |  Height: 67  |  Size: 2.5 KiB

BIN
static/flag/ee.png

After

Width: 100  |  Height: 64  |  Size: 158 B

BIN
static/flag/eg.png

After

Width: 100  |  Height: 67  |  Size: 1.1 KiB

BIN
static/flag/eh.png

After

Width: 100  |  Height: 50  |  Size: 656 B

BIN
static/flag/er.png

After

Width: 100  |  Height: 50  |  Size: 1.4 KiB

BIN
static/flag/es.png

After

Width: 100  |  Height: 67  |  Size: 1.7 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save