Merge branch 'milestone-20251031-简版功能开发' into maziyang/feature-20251025172218-智能客服中台
zhaowenkang/feature-20251028181547-行情页面
-
6.hbuilderx/launch.json
-
88api/deepExploration/deepExploration.js
-
0api/deepMate.js
-
68api/deepMate/deepMate.js
-
116api/start/login.js
-
260api/tcpConnection.js
-
392common/canvasMethod.js
-
354common/stockTimeInformation.js
-
123common/util.js
-
42components/DeepMate.vue
-
4components/IndexCard.vue
-
58components/MarketOverview.vue
-
536components/deepExploration_header.vue
-
49components/footerBar.vue
-
183components/login-prompt.vue
-
54main.js
-
38manifest.json
-
469package-lock.json
-
10package.json
-
274pages.json
-
100pages/blank/institutionalTrendsBriefing.vue
-
100pages/blank/notice.vue
-
801pages/deepExploration/MainForceActions.vue
-
427pages/deepExploration/deepExploration.vue
-
354pages/deepExploration/stockSelectDetail.vue
-
1733pages/deepMate/deepMate.vue
-
28pages/home/deepExploration.vue
-
1214pages/home/home.vue
-
296pages/home/member.vue
-
655pages/marketSituation/chartExample.vue
-
493pages/marketSituation/countryMarket.vue
-
301pages/marketSituation/forexMetals.vue
-
62pages/marketSituation/globalIndex.vue
-
2258pages/marketSituation/marketCondition.vue
-
82pages/marketSituation/marketDetail.vue
-
757pages/marketSituation/marketOverview.vue
-
473pages/marketSituation/marketSituation.vue
-
86pages/setting/about.vue
-
218pages/setting/account.vue
-
85pages/setting/bind.vue
-
142pages/setting/email.vue
-
68pages/setting/font.vue
-
165pages/setting/general.vue
-
76pages/setting/introduce.vue
-
221pages/setting/market.vue
-
62pages/setting/message.vue
-
82pages/setting/newVersion.vue
-
144pages/setting/nextPwd.vue
-
171pages/setting/password.vue
-
143pages/setting/phone.vue
-
108pages/setting/push.vue
-
87pages/setting/server.vue
-
111pages/setting/share.vue
-
64pages/setting/theme.vue
-
1054pages/start/Registration/Registration.vue
-
1341pages/start/Registration/list.js
-
13pages/start/agreement/agreement.vue
-
56pages/start/index/index.vue
-
1341pages/start/login/list.js
-
1190pages/start/login/login.vue
-
69pages/start/login/verification.js
-
13pages/start/privacy/privacy.vue
-
1012pages/start/recoverPassword/recoverPassword.vue
-
170pages/start/select/select.vue
-
73pages/start/startup/startup.vue
-
138server/login.json
-
BINstatic/deepExploration-images/1.png
-
BINstatic/deepExploration-images/2.png
-
BINstatic/deepExploration-images/3.png
-
BINstatic/deepExploration-images/4.png
-
BINstatic/deepExploration-images/ASC.png
-
BINstatic/deepExploration-images/Americle.png
-
BINstatic/deepExploration-images/DESC.png
-
BINstatic/deepExploration-images/all.png
-
BINstatic/deepExploration-images/close.png
-
BINstatic/deepExploration-images/delete.png
-
BINstatic/deepExploration-images/history.png
-
BINstatic/deepExploration-images/icon1.png
-
BINstatic/deepExploration-images/icon2.png
-
BINstatic/deepExploration-images/icon3.png
-
BINstatic/deepExploration-images/icon4.png
-
BINstatic/deepExploration-images/last.png
-
BINstatic/deepExploration-images/next.png
-
BINstatic/deepExploration-images/notice.png
-
BINstatic/deepExploration-images/plus.png
-
BINstatic/deepExploration-images/search.png
-
BINstatic/deepExploration-images/showAll.png
-
BINstatic/flag/ad.png
-
BINstatic/flag/ae.png
-
BINstatic/flag/af.png
-
BINstatic/flag/ag.png
-
BINstatic/flag/ai.png
-
BINstatic/flag/al.png
-
BINstatic/flag/am.png
-
BINstatic/flag/an.png
-
BINstatic/flag/ao.png
-
BINstatic/flag/aq.png
-
BINstatic/flag/ar.png
-
BINstatic/flag/as.png
-
BINstatic/flag/at.png
@ -0,0 +1,88 @@ |
|||||
|
import { http } from '@/utils/http.js' |
||||
|
|
||||
|
|
||||
|
//主力追踪意图
|
||||
|
export const getModel1First = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/trackingFirst', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
//主力追踪意图
|
||||
|
export const getModel1Second = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/trackingSecond', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
//主力追踪意图
|
||||
|
export const getModel2First = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/radarFirst', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
//主力追踪意图
|
||||
|
export const getModel2Second = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/radarSecond', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
//主力追踪意图
|
||||
|
export const getModel3First = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/decodingFirst', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
//主力追踪意图
|
||||
|
export const getModel3Second = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/decodingSecond', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
//主力追踪意图
|
||||
|
export const getModel4First = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/fundsFirst', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
//主力追踪意图
|
||||
|
export const getModel4Second = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/fundsSecond', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
//历史记录列表
|
||||
|
export const RecordListApi = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/coze/mainForceList', |
||||
|
data:data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
@ -0,0 +1,68 @@ |
|||||
|
import { http } from '../../utils/http' |
||||
|
|
||||
|
|
||||
|
|
||||
|
export const getData = () => { |
||||
|
return http({ |
||||
|
method: 'GET', |
||||
|
url: '/ka', |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 意图识别 |
||||
|
* POST /api/deepMate/dmFirst |
||||
|
* headers: token, content-type: application/json, contentType: application/json, version, client |
||||
|
* body: { content, language, marketList } |
||||
|
*/ |
||||
|
export const postIntent = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/deepMate/dmFirst', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 获取股票信息 |
||||
|
* headers: token, content-type: application/json, contentType: application/json, version, client |
||||
|
* body: { language, token, recordId, parentId, stockId } |
||||
|
*/ |
||||
|
export const postStock = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/deepMate/dmSecond', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 获取历史记录 |
||||
|
*/ |
||||
|
|
||||
|
export const postHistory = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/deepMate/dmList', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 历史记录详情 |
||||
|
*/ |
||||
|
|
||||
|
export const postHistoryDetail = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/api/deepMate/clickRecord', |
||||
|
data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
@ -0,0 +1,116 @@ |
|||||
|
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: 'POST', |
||||
|
url: '/UserLogin/login', |
||||
|
data: |
||||
|
data |
||||
|
, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 发送邮箱验证码 |
||||
|
* @param {*} email |
||||
|
* @returns |
||||
|
*/ |
||||
|
export const SendEmailCodeApi = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/UserLogin/sendEmail', |
||||
|
data: data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 发送手机验证码 |
||||
|
* @param {*} email |
||||
|
* @returns |
||||
|
*/ |
||||
|
export const SendPhoneCodeApi = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/UserLogin/sendPhone', |
||||
|
data:data |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
/** |
||||
|
* 注册 |
||||
|
*/ |
||||
|
|
||||
|
export const registerApi = (data) => { |
||||
|
return http({ |
||||
|
method: 'POST', |
||||
|
url: '/UserLogin/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, |
||||
|
}, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
|
||||
@ -0,0 +1,260 @@ |
|||||
|
/** |
||||
|
* TCP连接工具类 |
||||
|
* 用于处理TCP连接、发送消息和断开连接 |
||||
|
* |
||||
|
* @format |
||||
|
*/ |
||||
|
|
||||
|
// 引用TCP插件
|
||||
|
// const TCPSocket = uni.requireNativePlugin('Aimer-TCPPlugin');
|
||||
|
// const TCPSocket = uni.requireNativePlugin("Aimer-TCPPlugin");
|
||||
|
|
||||
|
// TCP连接配置
|
||||
|
const TCP_CONFIG = { |
||||
|
ip: "192.168.1.9", |
||||
|
port: "8080", |
||||
|
channel: "1", // 可选 1~20
|
||||
|
charsetname: "UTF-8", // 默认UTF-8,可选GBK
|
||||
|
}; |
||||
|
|
||||
|
/** |
||||
|
* TCP连接管理类 |
||||
|
*/ |
||||
|
class TCPConnection { |
||||
|
constructor() { |
||||
|
this.channelConnections = new Map(); // 存储每个channel的连接状态
|
||||
|
this.connectionCallbacks = []; |
||||
|
this.messageCallbacks = []; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* TCP初始化连接 |
||||
|
* @param {Object} config - 连接配置 {ip, port, channel, charsetname} |
||||
|
* @param {Function} callback - 连接状态回调函数 |
||||
|
*/ |
||||
|
connect(config = {}, callback = null) { |
||||
|
const channel = config.channel || TCP_CONFIG.channel; |
||||
|
|
||||
|
// 如果该channel已经连接,先断开现有连接
|
||||
|
if (this.channelConnections.get(channel)) { |
||||
|
console.log(`检测到channel ${channel}现有TCP连接,先断开...`); |
||||
|
this.disconnect(config); |
||||
|
// 等待断开完成后再连接
|
||||
|
setTimeout(() => { |
||||
|
this._performConnect(config, callback); |
||||
|
}, 300); |
||||
|
} else { |
||||
|
// 直接连接
|
||||
|
this._performConnect(config, callback); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 执行TCP连接 |
||||
|
* @param {Object} config - 连接配置 |
||||
|
* @param {Function} callback - 连接状态回调函数 |
||||
|
*/ |
||||
|
_performConnect(config = {}, callback = null) { |
||||
|
const connectionConfig = { |
||||
|
channel: config.channel || TCP_CONFIG.channel, |
||||
|
ip: config.ip || TCP_CONFIG.ip, |
||||
|
port: config.port || TCP_CONFIG.port, |
||||
|
}; |
||||
|
|
||||
|
// 如果指定了字符集,添加到配置中
|
||||
|
if (config.charsetname || TCP_CONFIG.charsetname) { |
||||
|
connectionConfig.charsetname = config.charsetname || TCP_CONFIG.charsetname; |
||||
|
} |
||||
|
|
||||
|
console.log('开始建立TCP连接:', connectionConfig); |
||||
|
TCPSocket.connect( |
||||
|
connectionConfig, |
||||
|
result => { |
||||
|
/** |
||||
|
* status : 0 连接成功 |
||||
|
* status : 1 断开连接 |
||||
|
* receivedMsg : 服务器返回字符串(普通的字符串交互) |
||||
|
* receivedHexMsg : 服务器返回字节数组(单片机、智能家居等硬件数据交互) |
||||
|
*/ |
||||
|
if (result.status == '0') { |
||||
|
// TCP连接成功
|
||||
|
this.channelConnections.set(connectionConfig.channel, true); |
||||
|
console.log(`TCP连接成功 - Channel ${connectionConfig.channel}`); |
||||
|
this._notifyConnectionCallbacks('connected', result, connectionConfig.channel); |
||||
|
} else if (result.status == '1') { |
||||
|
// TCP断开连接
|
||||
|
this.channelConnections.set(connectionConfig.channel, false); |
||||
|
console.log(`TCP断开连接 - Channel ${connectionConfig.channel}`); |
||||
|
this._notifyConnectionCallbacks('disconnected', result, connectionConfig.channel); |
||||
|
} |
||||
|
|
||||
|
if (result.receivedMsg) { |
||||
|
// 服务器返回字符串
|
||||
|
console.log('收到字符串消息:', result.receivedMsg); |
||||
|
this._notifyMessageCallbacks('string', result.receivedMsg, null, connectionConfig.channel); |
||||
|
} |
||||
|
|
||||
|
// if (result.receivedHexMsg) {
|
||||
|
// // 硬件服务器返回16进制数据
|
||||
|
// console.log('收到16进制消息:', result.receivedHexMsg);
|
||||
|
// let msg = result.receivedHexMsg;
|
||||
|
// let sum = msg.length / 2;
|
||||
|
// let arr = [];
|
||||
|
// for (let k = 0; k < sum; k++) {
|
||||
|
// let i = msg.substring(k * 2, k * 2 + 2);
|
||||
|
// arr.push(i);
|
||||
|
// }
|
||||
|
// console.log('解析后的16进制数组:', arr);
|
||||
|
// this._notifyMessageCallbacks('hex', result.receivedHexMsg, arr);
|
||||
|
// }
|
||||
|
|
||||
|
// 执行回调函数
|
||||
|
if (callback && typeof callback === "function") { |
||||
|
callback(result); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* TCP发送消息(普通的字符串交互) |
||||
|
* @param {String|Object} message - 要发送的消息,如果是对象会自动转换为JSON字符串 |
||||
|
* @param {Object} config - 发送配置 {channel, charsetname} |
||||
|
*/ |
||||
|
send(message, config = {}) { |
||||
|
const channel = config.channel || '1'; |
||||
|
|
||||
|
if (!this.channelConnections.get(channel)) { |
||||
|
console.warn(`TCP Channel ${channel}未连接,无法发送消息`); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// 如果message是对象,转换为JSON字符串
|
||||
|
let messageStr = message; |
||||
|
if (typeof message === "object") { |
||||
|
messageStr = JSON.stringify(message) + "\n"; |
||||
|
} |
||||
|
|
||||
|
const sendConfig = { |
||||
|
channel: config.channel || "1", // 注意:channel应该是字符串
|
||||
|
message: messageStr, |
||||
|
}; |
||||
|
|
||||
|
// 如果指定了字符编码,添加到配置中
|
||||
|
if (config.charsetname) { |
||||
|
sendConfig.charsetname = config.charsetname; |
||||
|
} |
||||
|
|
||||
|
TCPSocket.send(sendConfig); |
||||
|
console.log("js成功发送TCP消息:", messageStr); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* TCP断开连接 |
||||
|
* @param {Object} config - 断开配置 {channel} |
||||
|
*/ |
||||
|
disconnect(config = {}) { |
||||
|
const channel = config.channel || TCP_CONFIG.channel; |
||||
|
const disconnectConfig = { |
||||
|
channel: channel |
||||
|
}; |
||||
|
|
||||
|
TCPSocket.disconnect(disconnectConfig); |
||||
|
this.channelConnections.set(channel, false); |
||||
|
console.log(`TCP连接已断开 - Channel ${channel}`, disconnectConfig); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加连接状态监听器 |
||||
|
* @param {Function} callback - 回调函数 (status, result) => {} |
||||
|
*/ |
||||
|
onConnectionChange(callback) { |
||||
|
if (typeof callback === "function") { |
||||
|
this.connectionCallbacks.push(callback); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 添加消息监听器 |
||||
|
* @param {Function} callback - 回调函数 (type, message, parsedArray) => {} |
||||
|
*/ |
||||
|
onMessage(callback) { |
||||
|
if (typeof callback === "function") { |
||||
|
this.messageCallbacks.push(callback); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 移除连接状态监听器 |
||||
|
* @param {Function} callback - 要移除的回调函数 |
||||
|
*/ |
||||
|
removeConnectionListener(callback) { |
||||
|
const index = this.connectionCallbacks.indexOf(callback); |
||||
|
if (index > -1) { |
||||
|
this.connectionCallbacks.splice(index, 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 移除消息监听器 |
||||
|
* @param {Function} callback - 要移除的回调函数 |
||||
|
*/ |
||||
|
removeMessageListener(callback) { |
||||
|
const index = this.messageCallbacks.indexOf(callback); |
||||
|
if (index > -1) { |
||||
|
this.messageCallbacks.splice(index, 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取连接状态 |
||||
|
* @param {String} channel - 要检查的channel,如果不指定则返回所有channel的连接状态 |
||||
|
* @returns {Boolean|Object} 连接状态 |
||||
|
*/ |
||||
|
getConnectionStatus(channel = null) { |
||||
|
if (channel) { |
||||
|
return this.channelConnections.get(channel) || false; |
||||
|
} |
||||
|
// 返回所有channel的连接状态
|
||||
|
const allConnections = {}; |
||||
|
for (const [ch, status] of this.channelConnections) { |
||||
|
allConnections[ch] = status; |
||||
|
} |
||||
|
return allConnections; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 通知连接状态回调 |
||||
|
* @private |
||||
|
*/ |
||||
|
_notifyConnectionCallbacks(status, result, channel) { |
||||
|
this.connectionCallbacks.forEach(callback => { |
||||
|
try { |
||||
|
callback(status, result, channel); |
||||
|
} catch (error) { |
||||
|
console.error('连接状态回调执行错误:', error); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 通知消息回调 |
||||
|
* @private |
||||
|
*/ |
||||
|
_notifyMessageCallbacks(type, message, parsedArray = null, channel = null) { |
||||
|
this.messageCallbacks.forEach(callback => { |
||||
|
try { |
||||
|
callback(type, message, parsedArray, channel); |
||||
|
} catch (error) { |
||||
|
console.error('消息回调执行错误:', error); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 创建TCP连接实例
|
||||
|
const tcpConnection = new TCPConnection(); |
||||
|
|
||||
|
// 导出TCP连接实例和类
|
||||
|
export default tcpConnection; |
||||
|
export { TCPConnection, TCP_CONFIG }; |
||||
@ -0,0 +1,392 @@ |
|||||
|
/** |
||||
|
* 功能:Canvas绘制方法。 |
||||
|
* 作者:洪锡林 |
||||
|
* 时间:2025年10月25日 |
||||
|
* |
||||
|
* @format |
||||
|
*/ |
||||
|
|
||||
|
import { utils } from "./util.js"; |
||||
|
export const HCharts = { |
||||
|
// 清除画布
|
||||
|
clearCanvas(ctx, width, height) { |
||||
|
ctx.clearRect(0, 0, width, height); |
||||
|
ctx.setFillStyle("#ffffff"); |
||||
|
ctx.fillRect(0, 0, width, height); |
||||
|
}, |
||||
|
// 设置画布颜色
|
||||
|
setCanvasColor(ctx, width, height, color) { |
||||
|
ctx.clearRect(0, 0, width, height); |
||||
|
ctx.setFillStyle(color); |
||||
|
ctx.fillRect(0, 0, width, height); |
||||
|
}, |
||||
|
// 绘制文本工具函数
|
||||
|
drawText(ctx, text, x, y, fontSize = 12, color = "#333", align = "left") { |
||||
|
ctx.setFontSize(fontSize); |
||||
|
ctx.setFillStyle(color); |
||||
|
ctx.setTextAlign(align); |
||||
|
ctx.fillText(text, x, y); |
||||
|
}, |
||||
|
/** |
||||
|
* 功能:绘制网格系统。 |
||||
|
* 作者:洪锡林 |
||||
|
* 时间:2025年10月25日 |
||||
|
* |
||||
|
* grid:[{ |
||||
|
* top:顶部距离 |
||||
|
* bottom:底部距离 |
||||
|
* left:左侧距离 |
||||
|
* right:右侧距离 |
||||
|
* lineColor:网格线颜色 |
||||
|
* lineWidth:网格线宽度 |
||||
|
* horizontalLineNum:水平网格线数量 |
||||
|
* verticalLineNum:垂直网格线数量 |
||||
|
* label:{ |
||||
|
* fontSize:字体大小 |
||||
|
* color:字体颜色 |
||||
|
* onlyTwo:是否只有两个标签 |
||||
|
* text:[{ |
||||
|
* value:值标签 |
||||
|
* ratio:比例标签 |
||||
|
* },{ |
||||
|
* value:值标签 |
||||
|
* ratio:比例标签 |
||||
|
* },...] |
||||
|
* },...] |
||||
|
*/ |
||||
|
// 绘制网格系统
|
||||
|
drawGrid(ctx, width, height, grid, openTime, closeTime) { |
||||
|
// 测试数据
|
||||
|
// const preClosePrice = prevClosePrice;
|
||||
|
for (let i = 0; i < grid.length; ++i) { |
||||
|
const top = grid[i].top; |
||||
|
const bottom = grid[i].bottom; |
||||
|
const left = grid[i].left; |
||||
|
const right = grid[i].right; |
||||
|
const lineColor = grid[i].lineColor; |
||||
|
const lineWidth = grid[i].lineWidth; |
||||
|
const horizontalLineNum = grid[i].horizontalLineNum - 1; |
||||
|
const verticalLineNum = grid[i].verticalLineNum - 1; |
||||
|
let label; |
||||
|
if (grid[i].label) { |
||||
|
label = grid[i].label; |
||||
|
} |
||||
|
ctx.setStrokeStyle(lineColor); |
||||
|
ctx.setLineWidth(lineWidth); |
||||
|
|
||||
|
// 画图底的开盘收盘时间
|
||||
|
if (i == 0 && openTime && closeTime) { |
||||
|
HCharts.drawText(ctx, openTime, 6, height - bottom + 12, 14, "#686868", "left"); |
||||
|
HCharts.drawText(ctx, closeTime, width - 6, height - bottom + 12, 14, "#686868", "right"); |
||||
|
} |
||||
|
// 绘制水平网格线
|
||||
|
for (let j = 0; j <= horizontalLineNum; j++) { |
||||
|
const y = top + (j * (height - bottom - top)) / horizontalLineNum; |
||||
|
ctx.beginPath(); |
||||
|
if (label.lineStyle[j] == "dash") { |
||||
|
ctx.setLineDash([5, 5]); |
||||
|
} |
||||
|
ctx.moveTo(left, y); |
||||
|
ctx.lineTo(width - right, y); |
||||
|
ctx.stroke(); |
||||
|
ctx.setLineDash([]); |
||||
|
} |
||||
|
// 绘制垂直网格线
|
||||
|
for (let i = 0; i <= verticalLineNum; i++) { |
||||
|
const x = ((width - left - right) * i) / verticalLineNum; |
||||
|
ctx.beginPath(); |
||||
|
ctx.moveTo(x + left, top); |
||||
|
ctx.lineTo(x + left, height - bottom); |
||||
|
ctx.stroke(); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
// 绘制价格标签
|
||||
|
drawAxisLabels(ctx, width, height, grid) { |
||||
|
for (let i = 0; i < grid.length; ++i) { |
||||
|
const top = grid[i].top; |
||||
|
const bottom = grid[i].bottom; |
||||
|
const left = grid[i].left; |
||||
|
const right = grid[i].right; |
||||
|
const horizontalLineNum = grid[i].horizontalLineNum - 1; |
||||
|
let label; |
||||
|
if (grid[i].label) { |
||||
|
label = grid[i].label; |
||||
|
} |
||||
|
// 绘制水平网格线
|
||||
|
for (let j = 0; j <= horizontalLineNum; j++) { |
||||
|
const y = top + (j * (height - bottom - top)) / horizontalLineNum; |
||||
|
// 价格标签
|
||||
|
if (label) { |
||||
|
let valueXText = left + 1; |
||||
|
let ratioXText = width - right - 1; |
||||
|
let yText = y + 10; |
||||
|
if (j == horizontalLineNum) { |
||||
|
yText = y - 1; |
||||
|
} |
||||
|
let valueAlign = "left"; |
||||
|
let ratioAlign = "right"; |
||||
|
let fontSize = label.fontSize; |
||||
|
let textColor = label.color[j]; |
||||
|
if (label.onlyTwo) { |
||||
|
if (j == 0) { |
||||
|
HCharts.drawText(ctx, label.text[0].value, valueXText, yText, fontSize, label.color[0], valueAlign); |
||||
|
} else if (j == horizontalLineNum) { |
||||
|
HCharts.drawText(ctx, label.text[1].value, valueXText, yText, fontSize, label.color[1], valueAlign); |
||||
|
} |
||||
|
} else { |
||||
|
HCharts.drawText(ctx, label.text[j].value, valueXText, yText, fontSize, textColor, valueAlign); |
||||
|
} |
||||
|
|
||||
|
if (typeof label.text[j]?.ratio !== "undefined") { |
||||
|
HCharts.drawText(ctx, label.text[j].ratio, ratioXText, yText, fontSize, textColor, ratioAlign); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
// 绘制价格曲线
|
||||
|
drawPriceLine(ctx, width, height, data, grid, priceRange) { |
||||
|
if (!data.length) return; |
||||
|
// 上下边距1
|
||||
|
const top = grid[0].top; |
||||
|
const bottom = grid[0].bottom; |
||||
|
const left = grid[0].left; |
||||
|
const right = grid[0].right; |
||||
|
const pointLen = 240; |
||||
|
const priceDiff = priceRange.max - priceRange.min; |
||||
|
// 绘制价格曲线
|
||||
|
ctx.setStrokeStyle("#000"); |
||||
|
ctx.setLineWidth(1); |
||||
|
ctx.beginPath(); |
||||
|
|
||||
|
data.forEach((item, index) => { |
||||
|
const x = left + (index * (width - left - right)) / pointLen; |
||||
|
const y = top + (height - top - bottom) * (1 - (item.price - priceRange.min) / priceDiff); |
||||
|
if (index === 0) { |
||||
|
ctx.moveTo(x, y); |
||||
|
} else { |
||||
|
// 使用贝塞尔曲线平滑连接
|
||||
|
const prevPoint = data[index - 1]; |
||||
|
const prevX = left + ((index - 1) * (width - left - right)) / pointLen; |
||||
|
const prevY = top + (height - top + -bottom) * (1 - (prevPoint.price - priceRange.min) / priceDiff); |
||||
|
const cp1x = (prevX + x) / 2; |
||||
|
const cp1y = prevY; |
||||
|
const cp2x = (prevX + x) / 2; |
||||
|
const cp2y = y; |
||||
|
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); |
||||
|
} |
||||
|
}); |
||||
|
ctx.stroke(); |
||||
|
// 绘制渐变背景
|
||||
|
HCharts.drawGradientBackground(ctx, width, height, data, grid, priceRange); |
||||
|
}, |
||||
|
|
||||
|
// 绘制渐变背景
|
||||
|
drawGradientBackground(ctx, width, height, data, grid, priceRange) { |
||||
|
// 上下边距1
|
||||
|
const top = grid[0].top; |
||||
|
const bottom = grid[0].bottom; |
||||
|
const left = grid[0].left; |
||||
|
const right = grid[0].right; |
||||
|
const pointLen = 240; |
||||
|
const priceDiff = priceRange.max - priceRange.min; |
||||
|
|
||||
|
const gradient = ctx.createLinearGradient(0, left, 0, height - top); |
||||
|
gradient.addColorStop(0, "rgba(0, 0, 0, 0.3)"); |
||||
|
gradient.addColorStop(1, "rgba(0, 0, 0, 0.05)"); |
||||
|
|
||||
|
ctx.beginPath(); |
||||
|
|
||||
|
// 绘制价格曲线路径
|
||||
|
data.forEach((item, index) => { |
||||
|
const x = left + (index * (width - left - right)) / pointLen; |
||||
|
const y = top + (height - top - bottom) * (1 - (item.price - priceRange.min) / priceDiff); |
||||
|
|
||||
|
if (index === 0) { |
||||
|
ctx.moveTo(x, y); |
||||
|
} else { |
||||
|
const prevPoint = data[index - 1]; |
||||
|
const prevX = left + ((index - 1) * (width - left - right)) / pointLen; |
||||
|
const prevY = top + (height - top - bottom) * (1 - (prevPoint.price - priceRange.min) / priceDiff); |
||||
|
|
||||
|
const cp1x = (prevX + x) / 2; |
||||
|
const cp1y = prevY; |
||||
|
const cp2x = (prevX + x) / 2; |
||||
|
const cp2y = y; |
||||
|
|
||||
|
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 闭合路径
|
||||
|
const lastX = left + ((data.length - 1) * (width - left - right)) / pointLen; |
||||
|
ctx.lineTo(lastX, height - bottom); |
||||
|
ctx.lineTo(left, height - bottom); |
||||
|
ctx.closePath(); |
||||
|
|
||||
|
ctx.setFillStyle(gradient); |
||||
|
ctx.fill(); |
||||
|
}, |
||||
|
// 绘制成交量
|
||||
|
drawVolume(ctx, width, height, data, index, pointLen, grid, volumeRange, offset) { |
||||
|
if (!data.length) return; |
||||
|
|
||||
|
const top = grid[index - 1].top; |
||||
|
const bottom = grid[index - 1].bottom; |
||||
|
const left = grid[index - 1].left; |
||||
|
const right = grid[index - 1].right; |
||||
|
|
||||
|
data.forEach((item, index) => { |
||||
|
const x = offset + left + (index * (width - left - right)) / pointLen; |
||||
|
const barWidth = (width - left - right) / pointLen - 0.5; |
||||
|
const barHeight = (item.volume / volumeRange.max) * (height - bottom - top); |
||||
|
// 根据涨跌设置颜色
|
||||
|
const isRise = index === 0 || item.price >= data[index - 1].price || item.close >= data[index - 1].close; |
||||
|
ctx.setFillStyle(isRise ? "green" : "red"); |
||||
|
|
||||
|
ctx.fillRect(x - barWidth / 2, height - bottom - barHeight, barWidth, barHeight); |
||||
|
}); |
||||
|
}, |
||||
|
// 字符宽度近似计算(避免使用 measureText)
|
||||
|
getApproximateTextWidth(text, fontSize = 10) { |
||||
|
// 中文字符约等于 fontSize,英文字符约等于 fontSize * 0.6
|
||||
|
let width = 0; |
||||
|
for (let char of text) { |
||||
|
// 判断是否为中文字符
|
||||
|
if (char.match(/[\u4e00-\u9fa5]/)) { |
||||
|
width += fontSize; |
||||
|
} else { |
||||
|
width += fontSize * 0.6; |
||||
|
} |
||||
|
} |
||||
|
return width; |
||||
|
}, |
||||
|
// 绘制顶部价格显示
|
||||
|
drawTopPriceDisplay(ctx, grid, text) { |
||||
|
for (let i = 0; i < text.length; i++) { |
||||
|
let x = grid[i].left; |
||||
|
let y = grid[i].top - 4; |
||||
|
for (let j = 0; j < text[i].length; j++) { |
||||
|
ctx.setFillStyle(text[i][j].color); |
||||
|
ctx.setFontSize(10); |
||||
|
ctx.setTextAlign("left"); |
||||
|
ctx.fillText(text[i][j].name + ":" + text[i][j].value, x, y); |
||||
|
x += HCharts.getApproximateTextWidth(text[i][j].name + ":" + text[i][j].value) + 5; |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
// 绘制坐标轴标签
|
||||
|
drawCrosshairAxisLabels(ctx, width, height, grid, crosshair) { |
||||
|
const { x, y } = crosshair; |
||||
|
// X轴时间标签
|
||||
|
if (crosshair.currentData && (crosshair.currentData.time || crosshair.currentData.date)) { |
||||
|
const timeText = crosshair.currentData.time || crosshair.currentData.date; |
||||
|
const xBoxWidth = crosshair.currentData.time ? 40 : 70; |
||||
|
const xBoxHeight = 15; |
||||
|
ctx.setFillStyle("#629AF5"); |
||||
|
|
||||
|
if (x - xBoxWidth / 2 <= grid[0].left) { |
||||
|
ctx.fillRect(grid[0].left, height - grid[0].bottom, xBoxWidth, xBoxHeight); |
||||
|
} else if (x + xBoxWidth / 2 < width - grid[0].right) { |
||||
|
ctx.fillRect(x - xBoxWidth / 2, height - grid[0].bottom, xBoxWidth, xBoxHeight); |
||||
|
} else { |
||||
|
ctx.fillRect(width - grid[0].right - xBoxWidth, height - grid[0].bottom, xBoxWidth, xBoxHeight); |
||||
|
} |
||||
|
|
||||
|
ctx.setFillStyle("#fff"); |
||||
|
ctx.setFontSize(12); |
||||
|
ctx.setTextAlign("center"); |
||||
|
|
||||
|
if (x - xBoxWidth / 2 <= grid[0].left) { |
||||
|
ctx.fillText(timeText, grid[0].left + xBoxWidth / 2, height - grid[0].bottom + 12); |
||||
|
} else if (x + xBoxWidth / 2 < width - grid[0].right) { |
||||
|
ctx.fillText(timeText, x, height - grid[0].bottom + 12); |
||||
|
} else { |
||||
|
ctx.fillText(timeText, width - grid[0].right - xBoxWidth / 2, height - grid[0].bottom + 12); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Y轴价格标签
|
||||
|
if (crosshair.currentData) { |
||||
|
const priceText = utils.formatPrice(crosshair.currentData.price); |
||||
|
const yBoxWidth = 50; |
||||
|
const yBoxHeight = 14; |
||||
|
ctx.setFillStyle("#629AF5"); |
||||
|
if (x < grid[0].left + yBoxWidth + 5) { |
||||
|
ctx.fillRect(width - grid[0].right - yBoxWidth, y - yBoxHeight / 2, yBoxWidth, yBoxHeight); |
||||
|
} else { |
||||
|
ctx.fillRect(grid[0].left, y - yBoxHeight / 2, yBoxWidth, yBoxHeight); |
||||
|
} |
||||
|
|
||||
|
ctx.setFillStyle("#fff"); |
||||
|
ctx.setFontSize(11); |
||||
|
ctx.setTextAlign("center"); |
||||
|
if (x < grid[0].left + yBoxWidth + 5) { |
||||
|
ctx.fillText(priceText, width - grid[0].right - yBoxWidth / 2, y + 3); |
||||
|
} else { |
||||
|
ctx.fillText(priceText, grid[0].left + yBoxWidth / 2, y + 3); |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
// 绘制十字准线
|
||||
|
drawCrosshair(ctx, width, height, grid, crosshair, text) { |
||||
|
if (!ctx) return; |
||||
|
const { x, y } = crosshair; |
||||
|
if (crosshair.show) { |
||||
|
// 每次绘制前先清除整个画布
|
||||
|
ctx.clearRect(0, 0, width, height); |
||||
|
|
||||
|
// 绘制垂直准线1
|
||||
|
ctx.setStrokeStyle("#000"); |
||||
|
ctx.setLineWidth(1); |
||||
|
// ctx.setLineDash([5, 5]);
|
||||
|
|
||||
|
for (let i = 0; i < grid.length; i++) { |
||||
|
ctx.beginPath(); |
||||
|
ctx.moveTo(x, grid[i].top); |
||||
|
ctx.lineTo(x, height - grid[i].bottom); |
||||
|
ctx.stroke(); |
||||
|
} |
||||
|
// ctx.beginPath();
|
||||
|
// ctx.moveTo(x, grid[0].top);
|
||||
|
// ctx.lineTo(x, height - grid[0].bottom);
|
||||
|
// ctx.stroke();
|
||||
|
|
||||
|
// // 绘制垂直准线2
|
||||
|
// ctx.beginPath();
|
||||
|
// ctx.moveTo(x, grid[1].top);
|
||||
|
// ctx.lineTo(x, height - grid[1].bottom);
|
||||
|
// ctx.stroke();
|
||||
|
|
||||
|
// 绘制水平准线
|
||||
|
ctx.beginPath(); |
||||
|
ctx.moveTo(grid[0].left, y); |
||||
|
ctx.lineTo(width - grid[0].right, y); |
||||
|
ctx.stroke(); |
||||
|
|
||||
|
ctx.setLineDash([]); |
||||
|
|
||||
|
// 绘制焦点圆点 - 黑边白心(更小)
|
||||
|
// 先绘制白色填充
|
||||
|
ctx.setFillStyle("#ffffff"); |
||||
|
ctx.beginPath(); |
||||
|
ctx.arc(x, y, 2, 0, Math.PI * 2); |
||||
|
ctx.fill(); |
||||
|
|
||||
|
// 再绘制黑色边框
|
||||
|
ctx.setStrokeStyle("#000000"); |
||||
|
ctx.setLineWidth(1); |
||||
|
ctx.setLineDash([]); |
||||
|
ctx.beginPath(); |
||||
|
ctx.arc(x, y, 2, 0, Math.PI * 2); |
||||
|
ctx.stroke(); |
||||
|
|
||||
|
// 绘制坐标轴标签
|
||||
|
HCharts.drawCrosshairAxisLabels(ctx, width, height, grid, crosshair); |
||||
|
} |
||||
|
// 绘制顶部价格显示
|
||||
|
HCharts.drawTopPriceDisplay(ctx, grid, text); |
||||
|
ctx.draw(false); |
||||
|
}, |
||||
|
}; |
||||
@ -0,0 +1,354 @@ |
|||||
|
/** @format */ |
||||
|
|
||||
|
export const prevClosePrice = 14.95; // 前一日收盘价(元)
|
||||
|
export const timeData = [ |
||||
|
// 上午时段:9:30-11:30(共120个数据点)
|
||||
|
{ time: "09:30", price: 15.0, volume: 28500 }, // 开盘价15.00元,开盘放量
|
||||
|
{ time: "09:31", price: 15.08, volume: 25300 }, |
||||
|
{ time: "09:32", price: 15.12, volume: 22800 }, |
||||
|
{ time: "09:33", price: 15.09, volume: 19600 }, |
||||
|
{ time: "09:34", price: 15.15, volume: 17200 }, |
||||
|
{ time: "09:35", price: 15.18, volume: 15800 }, |
||||
|
{ time: "09:36", price: 15.16, volume: 14300 }, |
||||
|
{ time: "09:37", price: 15.2, volume: 13500 }, |
||||
|
{ time: "09:38", price: 15.17, volume: 12800 }, |
||||
|
{ time: "09:39", price: 15.22, volume: 12100 }, |
||||
|
{ time: "09:40", price: 15.25, volume: 11500 }, |
||||
|
{ time: "09:41", price: 15.23, volume: 10800 }, |
||||
|
{ time: "09:42", price: 15.26, volume: 10200 }, |
||||
|
{ time: "09:43", price: 15.24, volume: 9800 }, |
||||
|
{ time: "09:44", price: 15.28, volume: 9500 }, |
||||
|
{ time: "09:45", price: 15.3, volume: 9200 }, |
||||
|
{ time: "09:46", price: 15.27, volume: 8800 }, |
||||
|
{ time: "09:47", price: 15.29, volume: 8500 }, |
||||
|
{ time: "09:48", price: 15.32, volume: 8200 }, |
||||
|
{ time: "09:49", price: 15.3, volume: 7900 }, |
||||
|
{ time: "09:50", price: 15.33, volume: 7600 }, |
||||
|
{ time: "09:51", price: 15.31, volume: 7400 }, |
||||
|
{ time: "09:52", price: 15.34, volume: 7200 }, |
||||
|
{ time: "09:53", price: 15.32, volume: 7000 }, |
||||
|
{ time: "09:54", price: 15.35, volume: 6800 }, |
||||
|
{ time: "09:55", price: 15.33, volume: 6600 }, |
||||
|
{ time: "09:56", price: 15.36, volume: 6500 }, |
||||
|
{ time: "09:57", price: 15.34, volume: 6300 }, |
||||
|
{ time: "09:58", price: 15.37, volume: 6200 }, |
||||
|
{ time: "09:59", price: 15.35, volume: 6100 }, |
||||
|
{ time: "10:00", price: 15.38, volume: 6000 }, |
||||
|
{ time: "10:01", price: 15.36, volume: 5900 }, |
||||
|
{ time: "10:02", price: 15.39, volume: 5800 }, |
||||
|
{ time: "10:03", price: 15.37, volume: 5700 }, |
||||
|
{ time: "10:04", price: 15.4, volume: 5600 }, |
||||
|
{ time: "10:05", price: 15.38, volume: 5500 }, |
||||
|
{ time: "10:06", price: 15.41, volume: 15400 }, |
||||
|
{ time: "10:07", price: 15.39, volume: 5300 }, |
||||
|
{ time: "10:08", price: 15.42, volume: 5200 }, |
||||
|
{ time: "10:09", price: 15.4, volume: 5100 }, |
||||
|
{ time: "10:10", price: 15.43, volume: 5000 }, |
||||
|
{ time: "10:11", price: 15.41, volume: 5100 }, |
||||
|
{ time: "10:12", price: 15.44, volume: 5200 }, |
||||
|
{ time: "10:13", price: 15.42, volume: 5300 }, |
||||
|
{ time: "10:14", price: 15.45, volume: 5400 }, |
||||
|
{ time: "10:15", price: 15.43, volume: 5500 }, |
||||
|
{ time: "10:16", price: 15.46, volume: 5600 }, |
||||
|
{ time: "10:17", price: 15.44, volume: 5700 }, |
||||
|
{ time: "10:18", price: 15.47, volume: 5800 }, |
||||
|
{ time: "10:19", price: 15.45, volume: 5900 }, |
||||
|
{ time: "10:20", price: 15.48, volume: 6000 }, |
||||
|
{ time: "10:21", price: 15.46, volume: 6100 }, |
||||
|
{ time: "10:22", price: 15.49, volume: 6200 }, |
||||
|
{ time: "10:23", price: 15.47, volume: 6300 }, |
||||
|
{ time: "10:24", price: 15.5, volume: 6400 }, |
||||
|
{ time: "10:25", price: 15.48, volume: 6500 }, |
||||
|
{ time: "10:26", price: 15.51, volume: 6600 }, |
||||
|
{ time: "10:27", price: 15.49, volume: 6700 }, |
||||
|
{ time: "10:28", price: 15.52, volume: 6800 }, |
||||
|
{ time: "10:29", price: 15.5, volume: 6900 }, |
||||
|
{ time: "10:30", price: 15.53, volume: 7000 }, |
||||
|
{ time: "10:31", price: 15.51, volume: 7100 }, |
||||
|
{ time: "10:32", price: 15.54, volume: 7200 }, |
||||
|
{ time: "10:33", price: 15.52, volume: 7300 }, |
||||
|
{ time: "10:34", price: 15.55, volume: 7400 }, |
||||
|
{ time: "10:35", price: 15.53, volume: 7500 }, |
||||
|
{ time: "10:36", price: 15.56, volume: 7600 }, |
||||
|
{ time: "10:37", price: 15.54, volume: 7700 }, |
||||
|
{ time: "10:38", price: 15.57, volume: 7800 }, |
||||
|
{ time: "10:39", price: 15.55, volume: 7900 }, |
||||
|
{ time: "10:40", price: 15.58, volume: 8000 }, |
||||
|
{ time: "10:41", price: 15.56, volume: 8100 }, |
||||
|
{ time: "10:42", price: 15.59, volume: 8200 }, |
||||
|
{ time: "10:43", price: 15.57, volume: 8300 }, |
||||
|
{ time: "10:44", price: 15.6, volume: 8400 }, // 全天最高价15.60元
|
||||
|
{ time: "10:45", price: 15.58, volume: 8300 }, |
||||
|
{ time: "10:46", price: 15.56, volume: 8200 }, |
||||
|
{ time: "10:47", price: 15.54, volume: 8100 }, |
||||
|
{ time: "10:48", price: 15.52, volume: 8000 }, |
||||
|
{ time: "10:49", price: 15.5, volume: 7900 }, |
||||
|
{ time: "10:50", price: 15.48, volume: 7800 }, |
||||
|
{ time: "10:51", price: 15.46, volume: 7700 }, |
||||
|
{ time: "10:52", price: 15.44, volume: 7600 }, |
||||
|
{ time: "10:53", price: 15.42, volume: 7500 }, |
||||
|
{ time: "10:54", price: 15.4, volume: 7400 }, |
||||
|
{ time: "10:55", price: 15.38, volume: 7300 }, |
||||
|
{ time: "10:56", price: 15.36, volume: 7200 }, |
||||
|
{ time: "10:57", price: 15.34, volume: 7100 }, |
||||
|
{ time: "10:58", price: 15.32, volume: 7000 }, |
||||
|
{ time: "10:59", price: 15.3, volume: 6900 }, |
||||
|
{ time: "11:00", price: 15.28, volume: 6800 }, |
||||
|
{ time: "11:01", price: 15.26, volume: 6700 }, |
||||
|
{ time: "11:02", price: 15.24, volume: 6600 }, |
||||
|
{ time: "11:03", price: 15.22, volume: 6500 }, |
||||
|
{ time: "11:04", price: 15.2, volume: 6400 }, // 全天最低价15.20元
|
||||
|
{ time: "11:05", price: 15.22, volume: 6500 }, |
||||
|
{ time: "11:06", price: 15.24, volume: 6600 }, |
||||
|
{ time: "11:07", price: 15.26, volume: 6700 }, |
||||
|
{ time: "11:08", price: 15.28, volume: 6800 }, |
||||
|
{ time: "11:09", price: 15.3, volume: 6900 }, |
||||
|
{ time: "11:10", price: 15.32, volume: 7000 }, |
||||
|
{ time: "11:11", price: 15.34, volume: 7100 }, |
||||
|
{ time: "11:12", price: 15.36, volume: 7200 }, |
||||
|
{ time: "11:13", price: 15.38, volume: 7300 }, |
||||
|
{ time: "11:14", price: 15.4, volume: 7400 }, |
||||
|
{ time: "11:15", price: 15.42, volume: 7500 }, |
||||
|
{ time: "11:16", price: 15.44, volume: 7600 }, |
||||
|
{ time: "11:17", price: 15.46, volume: 7700 }, |
||||
|
{ time: "11:18", price: 15.48, volume: 7800 }, |
||||
|
{ time: "11:19", price: 15.5, volume: 7900 }, |
||||
|
{ time: "11:20", price: 15.45, volume: 8300 }, |
||||
|
{ time: "11:21", price: 15.47, volume: 8600 }, |
||||
|
{ time: "11:22", price: 15.43, volume: 9100 }, |
||||
|
{ time: "11:23", price: 15.46, volume: 9500 }, |
||||
|
{ time: "11:24", price: 15.49, volume: 10200 }, |
||||
|
{ time: "11:25", price: 15.5, volume: 11500 }, |
||||
|
{ time: "11:26", price: 15.48, volume: 12800 }, |
||||
|
{ time: "11:27", price: 15.52, volume: 14300 }, |
||||
|
{ time: "11:28", price: 15.5, volume: 16500 }, |
||||
|
{ time: "11:29", price: 15.53, volume: 19800 }, // 午盘收盘价15.53元
|
||||
|
|
||||
|
// 下午时段:13:00-15:00(共120个数据点)
|
||||
|
{ time: "13:00", price: 15.55, volume: 24600 }, // 午后开盘冲高
|
||||
|
{ time: "13:01", price: 15.58, volume: 21300 }, |
||||
|
{ time: "13:02", price: 15.6, volume: 18700 }, // 再次触及全天最高价
|
||||
|
{ time: "13:03", price: 15.57, volume: 16200 }, |
||||
|
{ time: "13:04", price: 15.55, volume: 14500 }, |
||||
|
{ time: "13:05", price: 15.52, volume: 12800 }, |
||||
|
{ time: "13:06", price: 15.5, volume: 11300 }, |
||||
|
{ time: "13:07", price: 15.48, volume: 10100 }, |
||||
|
{ time: "13:08", price: 15.5, volume: 9500 }, |
||||
|
{ time: "13:09", price: 15.47, volume: 8900 }, |
||||
|
{ time: "13:10", price: 15.45, volume: 8300 }, |
||||
|
{ time: "13:11", price: 15.43, volume: 7800 }, |
||||
|
{ time: "13:12", price: 15.46, volume: 7500 }, |
||||
|
{ time: "13:13", price: 15.44, volume: 7200 }, |
||||
|
{ time: "13:14", price: 15.42, volume: 6900 }, |
||||
|
{ time: "13:15", price: 15.45, volume: 6700 }, |
||||
|
{ time: "13:16", price: 15.43, volume: 6500 }, |
||||
|
{ time: "13:17", price: 15.4, volume: 6300 }, |
||||
|
{ time: "13:18", price: 15.42, volume: 6100 }, |
||||
|
{ time: "13:19", price: 15.39, volume: 5900 }, |
||||
|
{ time: "13:20", price: 15.41, volume: 5800 }, |
||||
|
{ time: "13:21", price: 15.39, volume: 5700 }, |
||||
|
{ time: "13:22", price: 15.42, volume: 5600 }, |
||||
|
{ time: "13:23", price: 15.4, volume: 5500 }, |
||||
|
{ time: "13:24", price: 15.43, volume: 5400 }, |
||||
|
{ time: "13:25", price: 15.41, volume: 5300 }, |
||||
|
{ time: "13:26", price: 15.44, volume: 5200 }, |
||||
|
{ time: "13:27", price: 15.42, volume: 5100 }, |
||||
|
{ time: "13:28", price: 15.45, volume: 5000 }, |
||||
|
{ time: "13:29", price: 15.43, volume: 5100 }, |
||||
|
{ time: "13:30", price: 15.46, volume: 5200 }, |
||||
|
{ time: "13:31", price: 15.44, volume: 5300 }, |
||||
|
{ time: "13:32", price: 15.47, volume: 5400 }, |
||||
|
{ time: "13:33", price: 15.45, volume: 5500 }, |
||||
|
{ time: "13:34", price: 15.48, volume: 5600 }, |
||||
|
{ time: "13:35", price: 15.46, volume: 5700 }, |
||||
|
{ time: "13:36", price: 15.49, volume: 5800 }, |
||||
|
{ time: "13:37", price: 15.47, volume: 5900 }, |
||||
|
{ time: "13:38", price: 15.5, volume: 6000 }, |
||||
|
{ time: "13:39", price: 15.48, volume: 6100 }, |
||||
|
{ time: "13:40", price: 15.51, volume: 6200 }, |
||||
|
{ time: "13:41", price: 15.49, volume: 6300 }, |
||||
|
{ time: "13:42", price: 15.52, volume: 6400 }, |
||||
|
{ time: "13:43", price: 15.5, volume: 6500 }, |
||||
|
{ time: "13:44", price: 15.53, volume: 6600 }, |
||||
|
{ time: "13:45", price: 15.51, volume: 6700 }, |
||||
|
{ time: "13:46", price: 15.54, volume: 6800 }, |
||||
|
{ time: "13:47", price: 15.52, volume: 6900 }, |
||||
|
{ time: "13:48", price: 15.55, volume: 7000 }, |
||||
|
{ time: "13:49", price: 15.53, volume: 7100 }, |
||||
|
{ time: "13:50", price: 15.56, volume: 7200 }, |
||||
|
{ time: "13:51", price: 15.54, volume: 7300 }, |
||||
|
{ time: "13:52", price: 15.57, volume: 7400 }, |
||||
|
{ time: "13:53", price: 15.55, volume: 7500 }, |
||||
|
{ time: "13:54", price: 15.58, volume: 7600 }, |
||||
|
{ time: "13:55", price: 15.56, volume: 7700 }, |
||||
|
{ time: "13:56", price: 15.59, volume: 7800 }, |
||||
|
{ time: "13:57", price: 15.57, volume: 7900 }, |
||||
|
{ time: "13:58", price: 15.6, volume: 8000 }, // 第三次触及全天最高价
|
||||
|
{ time: "13:59", price: 15.58, volume: 8100 }, |
||||
|
{ time: "14:00", price: 15.56, volume: 8200 }, |
||||
|
{ time: "14:01", price: 15.54, volume: 8300 }, |
||||
|
{ time: "14:02", price: 15.52, volume: 8400 }, |
||||
|
{ time: "14:03", price: 15.5, volume: 8300 }, |
||||
|
{ time: "14:04", price: 15.48, volume: 8200 }, |
||||
|
{ time: "14:05", price: 15.46, volume: 8100 }, |
||||
|
{ time: "14:06", price: 15.44, volume: 8000 }, |
||||
|
{ time: "14:07", price: 15.42, volume: 7900 }, |
||||
|
{ time: "14:08", price: 15.4, volume: 7800 }, |
||||
|
{ time: "14:09", price: 15.38, volume: 7700 }, |
||||
|
{ time: "14:10", price: 15.36, volume: 7600 }, |
||||
|
{ time: "14:11", price: 15.34, volume: 7500 }, |
||||
|
{ time: "14:12", price: 15.32, volume: 7400 }, |
||||
|
{ time: "14:13", price: 15.3, volume: 7300 }, |
||||
|
{ time: "14:14", price: 15.28, volume: 7200 }, |
||||
|
{ time: "14:15", price: 15.26, volume: 7100 }, |
||||
|
{ time: "14:16", price: 15.24, volume: 7000 }, |
||||
|
{ time: "14:17", price: 15.22, volume: 6900 }, |
||||
|
{ time: "14:18", price: 15.2, volume: 6800 }, // 再次触及全天最低价
|
||||
|
{ time: "14:19", price: 15.22, volume: 6700 }, |
||||
|
{ time: "14:20", price: 15.24, volume: 6600 }, |
||||
|
{ time: "14:21", price: 15.26, volume: 6500 }, |
||||
|
{ time: "14:22", price: 15.28, volume: 6400 }, |
||||
|
{ time: "14:23", price: 15.3, volume: 6300 }, |
||||
|
{ time: "14:24", price: 15.32, volume: 6200 }, |
||||
|
{ time: "14:25", price: 15.34, volume: 6100 }, |
||||
|
{ time: "14:26", price: 15.36, volume: 6000 }, |
||||
|
{ time: "14:27", price: 15.38, volume: 5900 }, |
||||
|
{ time: "14:28", price: 15.4, volume: 5800 }, |
||||
|
{ time: "14:29", price: 15.42, volume: 5700 }, |
||||
|
{ time: "14:30", price: 15.44, volume: 5600 }, |
||||
|
{ time: "14:31", price: 15.46, volume: 5500 }, |
||||
|
{ time: "14:32", price: 15.48, volume: 5400 }, |
||||
|
{ time: "14:33", price: 15.5, volume: 5300 }, |
||||
|
{ time: "14:34", price: 15.52, volume: 5200 }, |
||||
|
{ time: "14:35", price: 15.54, volume: 5100 }, |
||||
|
{ time: "14:36", price: 15.56, volume: 5000 }, |
||||
|
{ time: "14:37", price: 15.54, volume: 5100 }, |
||||
|
{ time: "14:38", price: 15.52, volume: 5200 }, |
||||
|
{ time: "14:39", price: 15.5, volume: 5300 }, |
||||
|
{ time: "14:40", price: 15.48, volume: 5400 }, |
||||
|
{ time: "14:41", price: 15.46, volume: 5500 }, |
||||
|
{ time: "14:42", price: 15.44, volume: 5600 }, |
||||
|
{ time: "14:43", price: 15.42, volume: 5700 }, |
||||
|
{ time: "14:44", price: 15.4, volume: 5800 }, |
||||
|
{ time: "14:45", price: 15.38, volume: 5900 }, |
||||
|
{ time: "14:46", price: 15.36, volume: 6000 }, |
||||
|
{ time: "14:47", price: 15.34, volume: 6100 }, |
||||
|
{ time: "14:48", price: 15.32, volume: 6200 }, |
||||
|
{ time: "14:49", price: 15.3, volume: 6300 }, |
||||
|
{ time: "14:50", price: 15.42, volume: 9800 }, // 尾盘开始放量
|
||||
|
{ time: "14:51", price: 15.45, volume: 11500 }, |
||||
|
{ time: "14:52", price: 15.43, volume: 13200 }, |
||||
|
{ time: "14:53", price: 15.46, volume: 15800 }, |
||||
|
{ time: "14:54", price: 15.44, volume: 18500 }, |
||||
|
{ time: "14:55", price: 15.47, volume: 21300 }, |
||||
|
{ time: "14:56", price: 15.45, volume: 24600 }, |
||||
|
{ time: "14:57", price: 15.48, volume: 27800 }, |
||||
|
{ time: "14:58", price: 15.46, volume: 31200 }, // 尾盘成交量峰值
|
||||
|
{ time: "14:59", price: 15.45, volume: 28500 }, // 当日收盘价15.45元
|
||||
|
]; |
||||
|
export const klineData = [ |
||||
|
// 第1天(起始点,位于区间中部)
|
||||
|
{ date: "2015-10-11", open: 16.5, high: 16.8, low: 16.2, close: 16.6, volume: 185000 }, |
||||
|
// 第2-90天(区间震荡:15.5-17.5元)
|
||||
|
{ date: "2015-10-12", open: 16.6, high: 16.9, low: 16.4, close: 16.7, volume: 192000 }, |
||||
|
{ date: "2015-10-13", open: 16.7, high: 17.0, low: 16.5, close: 16.6, volume: 188000 }, |
||||
|
{ date: "2015-10-14", open: 16.6, high: 16.8, low: 16.3, close: 16.4, volume: 175000 }, |
||||
|
{ date: "2015-10-15", open: 16.4, high: 16.7, low: 16.2, close: 16.5, volume: 181000 }, |
||||
|
{ date: "2015-10-16", open: 16.5, high: 16.9, low: 16.3, close: 16.8, volume: 195000 }, |
||||
|
{ date: "2015-10-17", open: 16.8, high: 17.1, low: 16.6, close: 16.7, volume: 202000 }, |
||||
|
{ date: "2015-10-18", open: 16.7, high: 16.9, low: 16.4, close: 16.5, volume: 183000 }, |
||||
|
{ date: "2015-10-19", open: 16.5, high: 16.7, low: 16.1, close: 16.3, volume: 172000 }, |
||||
|
{ date: "2015-10-20", open: 16.3, high: 16.6, low: 16.0, close: 16.4, volume: 178000 }, |
||||
|
{ date: "2015-10-21", open: 16.4, high: 16.8, low: 16.2, close: 16.6, volume: 189000 }, |
||||
|
{ date: "2015-10-22", open: 16.6, high: 17.0, low: 16.5, close: 16.9, volume: 205000 }, |
||||
|
{ date: "2015-10-23", open: 16.9, high: 17.2, low: 16.7, close: 16.8, volume: 212000 }, |
||||
|
{ date: "2015-10-24", open: 16.8, high: 17.0, low: 16.5, close: 16.6, volume: 193000 }, |
||||
|
{ date: "2015-10-25", open: 16.6, high: 16.8, low: 16.2, close: 16.3, volume: 176000 }, |
||||
|
{ date: "2015-10-26", open: 16.3, high: 16.6, low: 16.0, close: 16.5, volume: 184000 }, |
||||
|
{ date: "2015-10-27", open: 16.5, high: 16.9, low: 16.4, close: 16.7, volume: 196000 }, |
||||
|
{ date: "2015-10-28", open: 16.7, high: 17.1, low: 16.6, close: 16.9, volume: 208000 }, |
||||
|
{ date: "2015-10-29", open: 16.9, high: 17.3, low: 16.8, close: 17.0, volume: 215000 }, |
||||
|
{ date: "2015-10-30", open: 17.0, high: 17.2, low: 16.7, close: 16.8, volume: 201000 }, |
||||
|
{ date: "2015-10-31", open: 16.8, high: 17.0, low: 16.5, close: 16.6, volume: 189000 }, |
||||
|
{ date: "2015-11-01", open: 16.6, high: 16.8, low: 16.2, close: 16.4, volume: 175000 }, |
||||
|
{ date: "2015-11-02", open: 16.4, high: 16.7, low: 16.1, close: 16.3, volume: 171000 }, |
||||
|
{ date: "2015-11-03", open: 16.3, high: 16.6, low: 16.0, close: 16.5, volume: 182000 }, |
||||
|
{ date: "2015-11-04", open: 16.5, high: 16.9, low: 16.3, close: 16.7, volume: 194000 }, |
||||
|
{ date: "2015-11-05", open: 16.7, high: 17.1, low: 16.6, close: 16.8, volume: 203000 }, |
||||
|
{ date: "2015-11-06", open: 16.8, high: 17.0, low: 16.5, close: 16.6, volume: 190000 }, |
||||
|
{ date: "2015-11-07", open: 16.6, high: 16.8, low: 16.3, close: 16.4, volume: 178000 }, |
||||
|
{ date: "2015-11-08", open: 16.4, high: 16.7, low: 16.1, close: 16.3, volume: 173000 }, |
||||
|
{ date: "2015-11-09", open: 16.3, high: 16.6, low: 15.9, close: 16.2, volume: 168000 }, // 触及区间下沿
|
||||
|
{ date: "2015-11-10", open: 16.2, high: 16.5, low: 16.0, close: 16.4, volume: 176000 }, |
||||
|
{ date: "2015-11-11", open: 16.4, high: 16.8, low: 16.3, close: 16.6, volume: 187000 }, |
||||
|
{ date: "2015-11-12", open: 16.6, high: 17.0, low: 16.5, close: 16.8, volume: 198000 }, |
||||
|
{ date: "2015-11-13", open: 16.8, high: 17.2, low: 16.7, close: 16.9, volume: 206000 }, |
||||
|
{ date: "2015-11-14", open: 16.9, high: 17.3, low: 16.8, close: 17.1, volume: 218000 }, |
||||
|
{ date: "2015-11-15", open: 17.1, high: 17.4, low: 16.9, close: 17.0, volume: 212000 }, |
||||
|
{ date: "2015-11-16", open: 17.0, high: 17.2, low: 16.7, close: 16.8, volume: 197000 }, |
||||
|
{ date: "2015-11-17", open: 16.8, high: 17.0, low: 16.5, close: 16.6, volume: 185000 }, |
||||
|
{ date: "2015-11-18", open: 16.6, high: 16.8, low: 16.3, close: 16.4, volume: 177000 }, |
||||
|
{ date: "2015-11-19", open: 16.4, high: 16.7, low: 16.1, close: 16.3, volume: 172000 }, |
||||
|
{ date: "2015-11-20", open: 16.3, high: 16.6, low: 16.0, close: 16.5, volume: 183000 }, |
||||
|
{ date: "2015-11-21", open: 16.5, high: 16.9, low: 16.4, close: 16.7, volume: 195000 }, |
||||
|
{ date: "2015-11-22", open: 16.7, high: 17.1, low: 16.6, close: 16.9, volume: 204000 }, |
||||
|
{ date: "2015-11-23", open: 16.9, high: 17.2, low: 16.8, close: 17.0, volume: 213000 }, |
||||
|
{ date: "2015-11-24", open: 17.0, high: 17.3, low: 16.9, close: 17.1, volume: 221000 }, |
||||
|
{ date: "2015-11-25", open: 17.1, high: 17.4, low: 17.0, close: 17.2, volume: 228000 }, // 触及区间上沿
|
||||
|
{ date: "2015-11-26", open: 17.2, high: 17.3, low: 16.8, close: 16.9, volume: 215000 }, |
||||
|
{ date: "2015-11-27", open: 16.9, high: 17.1, low: 16.6, close: 16.7, volume: 199000 }, |
||||
|
{ date: "2015-11-28", open: 16.7, high: 16.9, low: 16.4, close: 16.5, volume: 186000 }, |
||||
|
{ date: "2015-11-29", open: 16.5, high: 16.7, low: 16.2, close: 16.3, volume: 175000 }, |
||||
|
{ date: "2015-11-30", open: 16.3, high: 16.6, low: 16.0, close: 16.4, volume: 179000 }, |
||||
|
{ date: "2015-12-01", open: 16.4, high: 16.8, low: 16.3, close: 16.6, volume: 188000 }, |
||||
|
{ date: "2015-12-02", open: 16.6, high: 17.0, low: 16.5, close: 16.8, volume: 199000 }, |
||||
|
{ date: "2015-12-03", open: 16.8, high: 17.2, low: 16.7, close: 16.9, volume: 207000 }, |
||||
|
{ date: "2015-12-04", open: 16.9, high: 17.1, low: 16.6, close: 16.7, volume: 193000 }, |
||||
|
{ date: "2015-12-05", open: 16.7, high: 16.9, low: 16.4, close: 16.5, volume: 182000 }, |
||||
|
{ date: "2015-12-06", open: 16.5, high: 16.7, low: 16.2, close: 16.3, volume: 173000 }, |
||||
|
{ date: "2015-12-07", open: 16.3, high: 16.6, low: 15.9, close: 16.1, volume: 167000 }, // 触及区间下沿
|
||||
|
{ date: "2015-12-08", open: 16.1, high: 16.4, low: 16.0, close: 16.3, volume: 174000 }, |
||||
|
{ date: "2015-12-09", open: 16.3, high: 16.7, low: 16.2, close: 16.5, volume: 185000 }, |
||||
|
{ date: "2015-12-10", open: 16.5, high: 16.9, low: 16.4, close: 16.7, volume: 196000 }, |
||||
|
{ date: "2015-12-11", open: 16.7, high: 17.1, low: 16.6, close: 16.9, volume: 205000 }, |
||||
|
{ date: "2015-12-12", open: 16.9, high: 17.3, low: 16.8, close: 17.0, volume: 214000 }, |
||||
|
{ date: "2015-12-13", open: 17.0, high: 17.2, low: 16.8, close: 16.9, volume: 203000 }, |
||||
|
{ date: "2015-12-14", open: 16.9, high: 17.1, low: 16.6, close: 16.7, volume: 191000 }, |
||||
|
{ date: "2015-12-15", open: 16.7, high: 16.9, low: 16.4, close: 16.5, volume: 180000 }, |
||||
|
{ date: "2015-12-16", open: 16.5, high: 16.7, low: 16.2, close: 16.3, volume: 172000 }, |
||||
|
{ date: "2015-12-17", open: 16.3, high: 16.6, low: 16.0, close: 16.4, volume: 178000 }, |
||||
|
{ date: "2015-12-18", open: 16.4, high: 16.8, low: 16.3, close: 16.6, volume: 189000 }, |
||||
|
{ date: "2015-12-19", open: 16.6, high: 17.0, low: 16.5, close: 16.8, volume: 200000 }, |
||||
|
{ date: "2015-12-20", open: 16.8, high: 17.2, low: 16.7, close: 16.9, volume: 208000 }, |
||||
|
{ date: "2015-12-21", open: 16.9, high: 17.3, low: 16.8, close: 17.1, volume: 219000 }, |
||||
|
{ date: "2015-12-22", open: 17.1, high: 17.4, low: 17.0, close: 17.2, volume: 226000 }, // 触及区间上沿
|
||||
|
{ date: "2015-12-23", open: 17.2, high: 17.3, low: 16.8, close: 16.9, volume: 213000 }, |
||||
|
{ date: "2015-12-24", open: 16.9, high: 17.1, low: 16.6, close: 16.7, volume: 198000 }, |
||||
|
{ date: "2015-12-25", open: 16.7, high: 16.9, low: 16.4, close: 16.5, volume: 185000 }, |
||||
|
{ date: "2015-12-26", open: 16.5, high: 16.7, low: 16.2, close: 16.3, volume: 174000 }, |
||||
|
{ date: "2015-12-27", open: 16.3, high: 16.6, low: 16.0, close: 16.5, volume: 183000 }, |
||||
|
{ date: "2015-12-28", open: 16.5, high: 16.9, low: 16.4, close: 16.7, volume: 195000 }, |
||||
|
{ date: "2015-12-29", open: 16.7, high: 17.1, low: 16.6, close: 16.9, volume: 204000 }, |
||||
|
{ date: "2015-12-30", open: 16.9, high: 17.2, low: 16.8, close: 17.0, volume: 212000 }, |
||||
|
{ date: "2015-12-31", open: 17.0, high: 17.3, low: 16.9, close: 17.1, volume: 220000 }, |
||||
|
{ date: "2016-01-01", open: 17.1, high: 17.2, low: 16.8, close: 16.9, volume: 207000 }, |
||||
|
{ date: "2016-01-02", open: 16.9, high: 17.1, low: 16.6, close: 16.7, volume: 193000 }, |
||||
|
{ date: "2016-01-03", open: 16.7, high: 16.9, low: 16.4, close: 16.5, volume: 181000 }, |
||||
|
{ date: "2016-01-04", open: 16.5, high: 16.7, low: 16.2, close: 16.3, volume: 172000 }, |
||||
|
{ date: "2016-01-05", open: 16.3, high: 16.6, low: 15.9, close: 16.2, volume: 168000 }, // 触及区间下沿
|
||||
|
{ date: "2016-01-06", open: 16.2, high: 16.5, low: 16.0, close: 16.4, volume: 175000 }, |
||||
|
{ date: "2016-01-07", open: 16.4, high: 16.8, low: 16.3, close: 16.6, volume: 186000 }, |
||||
|
{ date: "2016-01-08", open: 16.6, high: 17.0, low: 16.5, close: 16.8, volume: 197000 }, |
||||
|
{ date: "2016-01-09", open: 16.8, high: 17.2, low: 16.7, close: 16.9, volume: 206000 }, |
||||
|
{ date: "2016-01-10", open: 16.9, high: 17.3, low: 16.8, close: 17.1, volume: 217000 }, |
||||
|
{ date: "2016-01-11", open: 17.1, high: 17.4, low: 17.0, close: 17.2, volume: 225000 }, // 触及区间上沿
|
||||
|
{ date: "2016-01-12", open: 17.2, high: 17.3, low: 16.8, close: 16.9, volume: 212000 }, |
||||
|
{ date: "2016-01-13", open: 16.9, high: 17.1, low: 16.6, close: 16.7, volume: 197000 }, |
||||
|
{ date: "2016-01-14", open: 16.7, high: 16.9, low: 16.4, close: 16.5, volume: 184000 }, |
||||
|
{ date: "2016-01-15", open: 16.5, high: 16.7, low: 16.2, close: 16.4, volume: 175000 }, |
||||
|
{ date: "2016-01-16", open: 16.4, high: 16.7, low: 16.1, close: 16.3, volume: 171000 }, |
||||
|
{ date: "2016-01-17", open: 16.3, high: 16.6, low: 16.0, close: 16.5, volume: 182000 }, |
||||
|
{ date: "2016-01-18", open: 16.5, high: 16.9, low: 16.4, close: 16.7, volume: 194000 }, |
||||
|
{ date: "2016-01-19", open: 16.7, high: 17.1, low: 16.6, close: 16.9, volume: 203000 }, |
||||
|
{ date: "2016-01-20", open: 16.9, high: 17.2, low: 16.8, close: 17.0, volume: 212000 }, |
||||
|
]; |
||||
@ -0,0 +1,536 @@ |
|||||
|
<template> |
||||
|
<view class="titleContent"> |
||||
|
<view class="left"> |
||||
|
<uni-icons |
||||
|
@click="handleBack" |
||||
|
type="back" |
||||
|
size="23" |
||||
|
color="#111" |
||||
|
></uni-icons> |
||||
|
</view> |
||||
|
<view class="title">深度探索</view> |
||||
|
<view class="right"> |
||||
|
<image |
||||
|
class="notice" |
||||
|
src="/static/deepExploration-images/notice.png" |
||||
|
mode="aspectFill" |
||||
|
></image> |
||||
|
<image |
||||
|
@click="openHistoryDrawer" |
||||
|
class="history" |
||||
|
src="/static/deepExploration-images/history.png" |
||||
|
mode="aspectFill" |
||||
|
></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="drawer-overlay" v-show="showHistoryDrawer"></view> |
||||
|
|
||||
|
<view |
||||
|
class="drawer-panel" |
||||
|
v-show="showHistoryDrawer" |
||||
|
@click.stop |
||||
|
@touchmove.stop.prevent |
||||
|
:style="{ transform: 'translateY(' + drawerOffsetY + 'px)' }" |
||||
|
> |
||||
|
<view class="drawer-header"> |
||||
|
<text class="drawer-title">历史对话</text> |
||||
|
<view class="drawer-actions"> |
||||
|
<view class="delete-all-container"> |
||||
|
<image |
||||
|
class="delete-icon" |
||||
|
src="/static/icons/Group_48095481.svg" |
||||
|
></image> |
||||
|
<text class="delete-all" @click="clearAllHistory">删除全部</text> |
||||
|
</view> |
||||
|
<view class="drawer-close" @click="onDrawerBackClick" |
||||
|
><text class="drawer-close-icon"></text |
||||
|
></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<scroll-view scroll-y="true" class="drawer-content"> |
||||
|
<view class="drawer-inner"> |
||||
|
<view v-if="groupedHistory.length === 0" class="empty-history"> |
||||
|
<text>暂无历史记录</text> |
||||
|
</view> |
||||
|
<view |
||||
|
v-for="(section, sIdx) in groupedHistory" |
||||
|
:key="sIdx" |
||||
|
class="history-section" |
||||
|
> |
||||
|
<text class="section-title">{{ section.title }}</text> |
||||
|
<view |
||||
|
v-for="(item, idx) in section.items" |
||||
|
:key="idx" |
||||
|
class="history-item" |
||||
|
> |
||||
|
<view class="history-left"> |
||||
|
<view class="flag-circle" |
||||
|
><text class="flag-emoji">🇺🇸</text></view |
||||
|
> |
||||
|
</view> |
||||
|
<view class="history-main" @click="itemClick(item)"> |
||||
|
<text class="history-query">{{ item.stockName }}</text> |
||||
|
<text class="history-query">({{ item.stockCode }})</text> |
||||
|
</view> |
||||
|
<text class="history-time">{{ |
||||
|
formatTimeForHistory(item.createdTime) |
||||
|
}}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { RecordListApi } from "../api/deepExploration/deepExploration"; |
||||
|
import { ref, onMounted, computed } from "vue"; |
||||
|
|
||||
|
const props = defineProps({ |
||||
|
name: { |
||||
|
type: String, |
||||
|
default: "", |
||||
|
}, |
||||
|
}); |
||||
|
const showHistoryDrawer = ref(false); |
||||
|
const drawerOffsetY = ref(0); |
||||
|
// const handleHistory = () => { |
||||
|
// showHistoryDrawer.value = true; |
||||
|
// }; |
||||
|
|
||||
|
// 历史记录 |
||||
|
const openHistoryDrawer = async () => { |
||||
|
const res = await RecordListApi({ |
||||
|
model: 1, |
||||
|
}); |
||||
|
|
||||
|
if (res.code === 200) { |
||||
|
historyList.value = res.data; |
||||
|
} |
||||
|
|
||||
|
console.log("historyList.value", historyList.value); |
||||
|
|
||||
|
const hideDistance = uni.upx2px(900); |
||||
|
drawerOffsetY.value = hideDistance; |
||||
|
showHistoryDrawer.value = true; |
||||
|
setTimeout(() => { |
||||
|
drawerOffsetY.value = 0; |
||||
|
}, 10); |
||||
|
}; |
||||
|
|
||||
|
const clearAllHistory = () => { |
||||
|
searchHistory.value = []; |
||||
|
|
||||
|
// uni.setStorageSync("search_history", []); |
||||
|
}; |
||||
|
|
||||
|
//返回上一页 |
||||
|
const handleBack = () => { |
||||
|
uni.navigateBack(); |
||||
|
}; |
||||
|
|
||||
|
const closeHistoryDrawer = () => { |
||||
|
showHistoryDrawer.value = false; |
||||
|
}; |
||||
|
const onDrawerBackClick = () => { |
||||
|
const hideDistance = uni.upx2px(900); |
||||
|
drawerOffsetY.value = hideDistance; |
||||
|
setTimeout(() => { |
||||
|
closeHistoryDrawer(); |
||||
|
drawerOffsetY.value = 0; |
||||
|
}, 180); |
||||
|
}; |
||||
|
|
||||
|
// 历史记录详情 |
||||
|
async function itemClick(item) { |
||||
|
// const res = await postHistoryDetail({ |
||||
|
// recordId: item.id, |
||||
|
// parentId: item.parentId, |
||||
|
// model: 5, |
||||
|
// }); |
||||
|
// if (res.code == 200) { |
||||
|
// const message = res.data.wokeFlowData.One.markdown; |
||||
|
// messages.value = []; |
||||
|
// const botMsg = { |
||||
|
// content: message, |
||||
|
// isUser: false, |
||||
|
// isTyping: false, |
||||
|
// isThinking: false, |
||||
|
// }; |
||||
|
// messages.value.push(botMsg); |
||||
|
// } |
||||
|
} |
||||
|
const historyList = ref([ |
||||
|
{ |
||||
|
title: "今天", // 分组标题(如“今天”“昨天”“更早”) |
||||
|
items: [ |
||||
|
{ |
||||
|
icon: "/static/deepExploration-images/Americle.png", |
||||
|
stockName: "TechCore", // 股票名称 |
||||
|
stockCode: "600001", // 6位数字股票代码 |
||||
|
createdTime: "14:35", // 时间格式(时:分) |
||||
|
}, |
||||
|
{ |
||||
|
icon: "/static/deepExploration-images/Americle.png", |
||||
|
stockName: "MediaLink", |
||||
|
stockCode: "600002", |
||||
|
createdTime: "10:12", |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
title: "昨天", |
||||
|
items: [ |
||||
|
{ |
||||
|
icon: "/static/deepExploration-images/Americle.png", |
||||
|
stockName: "FinServ", |
||||
|
stockCode: "600003", |
||||
|
createdTime: "09:48", |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
]); |
||||
|
|
||||
|
// 为历史记录格式化时间:YYYY-MM-DD HH:mm |
||||
|
const formatTimeForHistory = (timeString) => { |
||||
|
// 假设 timeString 格式为 "YYYY-MM-DD HH:mm:ss" |
||||
|
const parts = timeString.split(" "); |
||||
|
if (parts.length >= 2) { |
||||
|
const datePart = parts[0]; |
||||
|
const timePart = parts[1]; |
||||
|
const timeParts = timePart.split(":"); |
||||
|
if (timeParts.length >= 2) { |
||||
|
return `${datePart} ${timeParts[0]}:${timeParts[1]}`; |
||||
|
} |
||||
|
} |
||||
|
return timeString; |
||||
|
}; |
||||
|
|
||||
|
// 历史分组(今天/昨天/近一周/按月) |
||||
|
const groupedHistory = computed(() => { |
||||
|
const sections = []; |
||||
|
|
||||
|
// 从缓存获取今天日期,如果没有则使用当前日期 |
||||
|
const now = new Date(); |
||||
|
|
||||
|
const startOfDay = (d) => |
||||
|
new Date(d.getFullYear(), d.getMonth(), d.getDate()); |
||||
|
const isSameDay = (a, b) => |
||||
|
startOfDay(a).getTime() === startOfDay(b).getTime(); |
||||
|
const isYesterday = (d) => { |
||||
|
const y = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1); |
||||
|
return isSameDay(d, y); |
||||
|
}; |
||||
|
const isToday = (d) => isSameDay(d, now); |
||||
|
const withinLast7Days = (d) => { |
||||
|
const seven = new Date( |
||||
|
now.getFullYear(), |
||||
|
now.getMonth(), |
||||
|
now.getDate() - 7 |
||||
|
); |
||||
|
return d >= seven && !isToday(d) && !isYesterday(d); |
||||
|
}; |
||||
|
const monthLabel = (d) => `${d.getMonth() + 1}月`; |
||||
|
|
||||
|
const today = []; |
||||
|
const yesterday = []; |
||||
|
const last7 = []; |
||||
|
const byMonth = new Map(); |
||||
|
|
||||
|
// 使用 historyList.value 替代 searchHistory.value |
||||
|
historyList.value.forEach((item) => { |
||||
|
// 根据你的数据结构,使用 createdTime 字段 |
||||
|
const dt = new Date(item.createdTime); |
||||
|
if (isToday(dt)) { |
||||
|
today.push(item); |
||||
|
} else if (isYesterday(dt)) { |
||||
|
yesterday.push(item); |
||||
|
} else if (withinLast7Days(dt)) { |
||||
|
last7.push(item); |
||||
|
} else { |
||||
|
const year = dt.getFullYear(); |
||||
|
const month = dt.getMonth() + 1; |
||||
|
const key = `${year}-${month}`; |
||||
|
if (!byMonth.has(key)) |
||||
|
byMonth.set(key, { |
||||
|
title: `${year}年${month}月`, |
||||
|
year, |
||||
|
month, |
||||
|
items: [], |
||||
|
}); |
||||
|
byMonth.get(key).items.push(item); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
if (today.length) sections.push({ title: "今天", items: today }); |
||||
|
if (yesterday.length) sections.push({ title: "昨天", items: yesterday }); |
||||
|
if (last7.length) sections.push({ title: "近一周", items: last7 }); |
||||
|
|
||||
|
const monthSections = Array.from(byMonth.values()).sort((a, b) => { |
||||
|
if (a.year !== b.year) return b.year - a.year; |
||||
|
return b.month - a.month; // 月份倒序,如 10月 在 9月 之前 |
||||
|
}); |
||||
|
sections.push(...monthSections); |
||||
|
|
||||
|
return sections; |
||||
|
}); |
||||
|
|
||||
|
onMounted(() => {}); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
* { |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
|
||||
|
.titleContent { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
padding: 30rpx 60rpx 40rpx 35rpx; |
||||
|
box-shadow: 2rpx 2rpx 8rpx rgba(0, 0, 0, 0.1); |
||||
|
|
||||
|
.left { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
width: 36rpx; |
||||
|
height: 36rpx; |
||||
|
} |
||||
|
|
||||
|
.title { |
||||
|
position: absolute; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
color: #000000; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 19px; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 25px; |
||||
|
} |
||||
|
|
||||
|
.right { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 20rpx; |
||||
|
|
||||
|
.notice { |
||||
|
width: 35rpx; |
||||
|
height: 35rpx; |
||||
|
gap: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.history { |
||||
|
width: 32rpx; |
||||
|
height: 32rpx; |
||||
|
align-items: center; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 搜索历史侧拉框样式 */ |
||||
|
.drawer-overlay { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, 0.35); |
||||
|
z-index: 900; |
||||
|
} |
||||
|
|
||||
|
.drawer-panel { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
height: 75vh; |
||||
|
max-height: 80vh; |
||||
|
width: 100%; |
||||
|
background: #ffffff; |
||||
|
box-shadow: 0 -8rpx 20rpx rgba(0, 0, 0, 0.06); |
||||
|
z-index: 1000; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
border-top-left-radius: 20rpx; |
||||
|
border-top-right-radius: 20rpx; |
||||
|
transition: transform 0.22s ease; |
||||
|
} |
||||
|
|
||||
|
.drawer-back { |
||||
|
position: absolute; |
||||
|
left: 50%; |
||||
|
top: -14px; |
||||
|
transform: translateX(-50%); |
||||
|
width: 28px; |
||||
|
height: 48px; |
||||
|
border-radius: 12px; |
||||
|
background: #fff; |
||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08); |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.drawer-back-icon { |
||||
|
font-size: 16px; |
||||
|
color: #8a8a8a; |
||||
|
} |
||||
|
|
||||
|
.drawer-actions { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 40rpx; |
||||
|
} |
||||
|
|
||||
|
.delete-all-container { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 14rpx; |
||||
|
} |
||||
|
|
||||
|
.delete-icon { |
||||
|
width: 28rpx; |
||||
|
height: 32rpx; |
||||
|
} |
||||
|
|
||||
|
.delete-all { |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.drawer-close { |
||||
|
background: url("../static/icons/关闭2.svg"); |
||||
|
width: 48rpx; |
||||
|
height: 48rpx; |
||||
|
border-radius: 24rpx; |
||||
|
/* background: #f5f5f5; */ |
||||
|
/* box-shadow: 0 2px 8px rgba(0,0,0,0.08); */ |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
|
||||
|
image { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.drawer-header { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
padding: 52rpx 28rpx 0rpx 28rpx; |
||||
|
/* border-bottom: 2rpx solid #f0f0f0; */ |
||||
|
} |
||||
|
|
||||
|
.drawer-title { |
||||
|
font-size: 32rpx; |
||||
|
font-weight: 600; |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.drawer-content { |
||||
|
flex: 1; |
||||
|
min-height: 0; |
||||
|
/* 让 flex 子元素可在容器内收缩以启用滚动 */ |
||||
|
height: 100%; |
||||
|
overscroll-behavior-y: contain; |
||||
|
/* 防止滚动串联到页面 */ |
||||
|
-webkit-overflow-scrolling: touch; |
||||
|
/* iOS 惯性滚动 */ |
||||
|
touch-action: pan-y; |
||||
|
/* 优化触控滚动,仅垂直 */ |
||||
|
} |
||||
|
|
||||
|
.drawer-inner { |
||||
|
padding: 20rpx 24rpx 20rpx 24rpx; |
||||
|
} |
||||
|
|
||||
|
.history-section { |
||||
|
margin-bottom: 20rpx; |
||||
|
/* margin: 0 24rpx; */ |
||||
|
} |
||||
|
|
||||
|
.section-title { |
||||
|
font-size: 26rpx; |
||||
|
color: #888; |
||||
|
margin: 10rpx 6rpx 16rpx; |
||||
|
} |
||||
|
|
||||
|
.history-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
padding: 19rpx 18rpx; |
||||
|
background-color: #f6f7f9; |
||||
|
border-radius: 12rpx; |
||||
|
margin-bottom: 12rpx; |
||||
|
} |
||||
|
|
||||
|
.history-left { |
||||
|
margin-right: 20rpx; |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.flag-circle { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
border-radius: 50%; |
||||
|
background: #fff; |
||||
|
border: 2rpx solid #eee; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
image { |
||||
|
width: 50rpx; |
||||
|
height: 50rpx; |
||||
|
border-radius: 50%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.history-main { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.history-query { |
||||
|
color: #000000; |
||||
|
text-align: center; |
||||
|
font-size: 24rpx; |
||||
|
font-weight: 400; |
||||
|
line-height: 40rpx; |
||||
|
} |
||||
|
|
||||
|
.history-time { |
||||
|
font-size: 22rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.history-card { |
||||
|
background-color: #fff; |
||||
|
border: 2rpx solid #f2f2f2; |
||||
|
border-left: 8rpx solid rgb(220, 31, 29); |
||||
|
border-radius: 12rpx; |
||||
|
padding: 18rpx 20rpx; |
||||
|
margin-bottom: 16rpx; |
||||
|
box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.03); |
||||
|
} |
||||
|
|
||||
|
.history-query { |
||||
|
font-size: 28rpx; |
||||
|
color: #333333; |
||||
|
font-weight: 500; |
||||
|
} |
||||
|
|
||||
|
.history-time { |
||||
|
margin-top: 8rpx; |
||||
|
font-size: 22rpx; |
||||
|
color: #888888; |
||||
|
} |
||||
|
|
||||
|
.empty-history { |
||||
|
padding: 40rpx; |
||||
|
color: #999999; |
||||
|
text-align: center; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,183 @@ |
|||||
|
<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, onMounted } from "vue"; |
||||
|
import { useUserStore } from "../stores/modules/userInfo"; |
||||
|
import { useDeviceStore } from "../stores/modules/deviceInfo"; |
||||
|
import { LoginApi } from "../api/start/login"; |
||||
|
const deviceId = ref(""); |
||||
|
|
||||
|
const userStore = useUserStore(); |
||||
|
const deviceStore = useDeviceStore(); |
||||
|
// 初始化 |
||||
|
onMounted(() => { |
||||
|
if (!userStore.userInfo) { |
||||
|
show(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 定义响应式数据 |
||||
|
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 = async () => { |
||||
|
// 设置访客模式 |
||||
|
const res = await LoginApi({ |
||||
|
loginType: "VISITOR", //登录方式EMAIL,PHONE,DCCODE,APPLE,GOOGLE,VISITOR |
||||
|
account: "", //登陆账号 手机号/邮箱/dccode |
||||
|
verifyCode: "", //验证码 |
||||
|
password: "", //密码 |
||||
|
useCode: "", //是否使用验证码 true/false |
||||
|
idToken: "", //第三方登录idToken |
||||
|
deviceId: deviceStore.deviceInfo.deviceId, |
||||
|
}); |
||||
|
|
||||
|
if (res.code === 200) { |
||||
|
userStore.setUserInfo(res.data); |
||||
|
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> |
||||
@ -1,5 +1,13 @@ |
|||||
{ |
{ |
||||
"dependencies": { |
"dependencies": { |
||||
"vue-i18n": "^9.14.5" |
|
||||
|
"@dcloudio/uni-ui": "^1.5.11", |
||||
|
"@element-plus/icons-vue": "^2.3.2", |
||||
|
"element-plus": "^2.11.5", |
||||
|
"vue-i18n": "^9.14.5", |
||||
|
"marked": "^2.0.1", |
||||
|
"pinia": "^3.0.3", |
||||
|
"pinia-plugin-persistedstate": "^4.5.0" |
||||
} |
} |
||||
|
|
||||
|
|
||||
} |
} |
||||
@ -0,0 +1,100 @@ |
|||||
|
<template> |
||||
|
|
||||
|
<view class="blank-page"> |
||||
|
<view class="header" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"> |
||||
|
<!-- 返回按钮 --> |
||||
|
<view class="head-left"> |
||||
|
<image class="back-button" @click="goBack" src="/static/icons/Left_(左).png"> |
||||
|
|
||||
|
|
||||
|
<!-- <text class="tip">当前特斯拉该如何布局?</text> --> |
||||
|
</image> |
||||
|
</view> |
||||
|
<view class="header-center"> |
||||
|
<text class="title" :style="{ paddingTop: safeAreaInsets?.top + 'px' }" |
||||
|
>机构动向解析</text |
||||
|
> |
||||
|
</view> |
||||
|
</view> |
||||
|
<image class="picture" src="/static/images/缺省.png" /> |
||||
|
<text class="tip">暂无内容~</text> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
// 返回到 deepMate 页面 |
||||
|
const goBack = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/deepMate/deepMate' |
||||
|
}); |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.blank-page { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
position: fixed; |
||||
|
/* 充满视口,彻底禁用页面滚动 */ |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
height: 100vh; |
||||
|
overflow: hidden; |
||||
|
/* 锁定页面滚动 */ |
||||
|
background-color: #ffffff; |
||||
|
padding: 20rpx 0rpx; |
||||
|
} |
||||
|
.header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 20rpx 30rpx; |
||||
|
background-color: #ffffff; |
||||
|
box-shadow: 0 2rpx rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
.head-left { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
.back-button { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
} |
||||
|
.header-center .title { |
||||
|
position: fixed; |
||||
|
top: 25rpx; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
font-size: 36rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333333; |
||||
|
} |
||||
|
.back-button:hover { |
||||
|
background-color: #e0e0e0; |
||||
|
} |
||||
|
|
||||
|
.back-button:active { |
||||
|
transform: scale(0.95); |
||||
|
} |
||||
|
|
||||
|
.back-icon { |
||||
|
font-size: 32rpx; |
||||
|
color: #333333; |
||||
|
margin-right: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.picture { |
||||
|
display: block; |
||||
|
margin: 200rpx auto 0; /* 图片水平居中 */ |
||||
|
width: 60%; |
||||
|
height: 600rpx; |
||||
|
} |
||||
|
.tip { |
||||
|
color: #999999; |
||||
|
font-size: 28rpx; |
||||
|
text-align: center; |
||||
|
margin-top: 20rpx; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,100 @@ |
|||||
|
<template> |
||||
|
|
||||
|
<view class="blank-page"> |
||||
|
<view class="header" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"> |
||||
|
<!-- 返回按钮 --> |
||||
|
<view class="head-left"> |
||||
|
<image class="back-button" @click="goBack" src="/static/icons/Left_(左).png"> |
||||
|
|
||||
|
|
||||
|
<!-- <text class="tip">当前特斯拉该如何布局?</text> --> |
||||
|
</image> |
||||
|
</view> |
||||
|
<view class="header-center"> |
||||
|
<text class="title" :style="{ paddingTop: safeAreaInsets?.top + 'px' }" |
||||
|
>消息推送通知</text |
||||
|
> |
||||
|
</view> |
||||
|
</view> |
||||
|
<image class="picture" src="/static/images/缺省.png" /> |
||||
|
<text class="tip">暂无内容~</text> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
// 返回到 deepMate 页面 |
||||
|
const goBack = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/deepMate/deepMate' |
||||
|
}); |
||||
|
}; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.blank-page { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
position: fixed; |
||||
|
/* 充满视口,彻底禁用页面滚动 */ |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
height: 100vh; |
||||
|
overflow: hidden; |
||||
|
/* 锁定页面滚动 */ |
||||
|
background-color: #ffffff; |
||||
|
padding: 20rpx 0rpx; |
||||
|
} |
||||
|
.header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 20rpx 30rpx; |
||||
|
background-color: #ffffff; |
||||
|
box-shadow: 0 2rpx rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
.head-left { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
.back-button { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
} |
||||
|
.header-center .title { |
||||
|
position: fixed; |
||||
|
top: 25rpx; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
font-size: 36rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333333; |
||||
|
} |
||||
|
.back-button:hover { |
||||
|
background-color: #e0e0e0; |
||||
|
} |
||||
|
|
||||
|
.back-button:active { |
||||
|
transform: scale(0.95); |
||||
|
} |
||||
|
|
||||
|
.back-icon { |
||||
|
font-size: 32rpx; |
||||
|
color: #333333; |
||||
|
margin-right: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.picture { |
||||
|
display: block; |
||||
|
margin: 200rpx auto 0; /* 图片水平居中 */ |
||||
|
width: 60%; |
||||
|
height: 600rpx; |
||||
|
} |
||||
|
.tip { |
||||
|
color: #999999; |
||||
|
font-size: 28rpx; |
||||
|
text-align: center; |
||||
|
margin-top: 20rpx; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,801 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<!-- 顶部状态栏占位 --> |
||||
|
<view class="top" :style="{height:iSMT+'px'}"></view> |
||||
|
<deepExploration_header></deepExploration_header> |
||||
|
|
||||
|
<view class="search"> |
||||
|
<input v-model="searchName" class="searchInput" type="text" placeholder="请输入股票名称、股票代码" |
||||
|
placeholder-style="color: #A6A6A6; font-size: 22rpx;" /> |
||||
|
<image @click="searchStock" class="seachIcon" src="/static/deepExploration-images/search.png" |
||||
|
mode="aspectFill"></image> |
||||
|
</view> |
||||
|
|
||||
|
<view class="content"> |
||||
|
<view class="select"> |
||||
|
<image class="img" :src="navItems[currentIndex].icon" mode=""></image> |
||||
|
<view v-for="(item, index) in navItems" :key="index" class="selectItem" |
||||
|
:class="{ active: currentIndex === index }" @click="handleModel(index)"> |
||||
|
<button class="btn"></button> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="graphAndTxt"> |
||||
|
<view class="graph"> |
||||
|
<view class="graph_header"> |
||||
|
<view class="left">TESA</view> |
||||
|
<view class="center"> |
||||
|
<image class="last" src="/static/deepExploration-images/last.png" mode="aspectFill"></image> |
||||
|
<text>Taewlkj.sejssssssssf</text> |
||||
|
<image class="next" src="/static/deepExploration-images/next.png" mode="aspectFill"></image> |
||||
|
</view> |
||||
|
<view class="right">2025/10/26</view> |
||||
|
</view> |
||||
|
<view class="graph_data"> |
||||
|
<text>435.900</text> |
||||
|
<text>22.410</text> |
||||
|
<text>5.120%</text> |
||||
|
</view> |
||||
|
<view class="graph_content"> |
||||
|
<view class="charts-box"> |
||||
|
<!-- uCharts 蜡烛图组件 --> |
||||
|
<qiun-data-charts type="candle" :opts="opts" :chartData="chartData" :disableScroll="true" |
||||
|
:ontouch="true" :onzoom="true" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="txt"> |
||||
|
<view class="txtHeader"> |
||||
|
<image src="/static/deepExploration-images/plus.png" mode="aspectFill"></image> |
||||
|
<text>主力追踪</text> |
||||
|
</view> |
||||
|
<view class="txtContent"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部切换栏 --> |
||||
|
<footerBar class="static-footer" :type="type"></footerBar> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
import deepExploration_header from '@/components/deepExploration_header.vue' |
||||
|
import footerBar from '@/components/footerBar.vue' |
||||
|
import { |
||||
|
onLoad |
||||
|
} from '@dcloudio/uni-app' |
||||
|
import { |
||||
|
getModel1First, |
||||
|
getModel1Second, |
||||
|
getModel2First, |
||||
|
getModel2Second, |
||||
|
getModel3First, |
||||
|
getModel3Second, |
||||
|
getModel4First, |
||||
|
getModel4Second, |
||||
|
} from '/api/deepExploration/deepExploration.js' |
||||
|
|
||||
|
// 响应式变量定义 |
||||
|
const type = ref('deepExploration') |
||||
|
const iSMT = ref(0) |
||||
|
const currentIndex = ref(0) |
||||
|
const navItems = ref([{ |
||||
|
name: '主力追踪', |
||||
|
icon: '/static/deepExploration-images/1.png' |
||||
|
}, |
||||
|
{ |
||||
|
name: '主力雷达', |
||||
|
icon: '/static/deepExploration-images/2.png' |
||||
|
}, |
||||
|
{ |
||||
|
name: '主力解码', |
||||
|
icon: '/static/deepExploration-images/3.png' |
||||
|
}, |
||||
|
{ |
||||
|
name: '主力资金流', |
||||
|
icon: '/static/deepExploration-images/4.png' |
||||
|
}, |
||||
|
]) |
||||
|
|
||||
|
//搜索股票 |
||||
|
const searchStock = () => { |
||||
|
console.log('搜索参数:', stockName.value); |
||||
|
if (currentIndex.value == 0) { |
||||
|
handleModel(0) |
||||
|
} else if (currentIndex.value == 1) { |
||||
|
console.log(index); |
||||
|
handleModel(1) |
||||
|
} else if (currentIndex.value == 2) { |
||||
|
console.log(index); |
||||
|
handleModel(2) |
||||
|
} else if (currentIndex.value == 3) { |
||||
|
console.log(index); |
||||
|
handleModel(3) |
||||
|
}else{ |
||||
|
uni.showToast({ |
||||
|
title: '请选择模块', |
||||
|
icon: 'none', |
||||
|
duration: 2000 |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
//点击四大模块 |
||||
|
const handleModel = (index) => { |
||||
|
currentIndex.value = index |
||||
|
if (currentIndex.value == 0) { |
||||
|
console.log(index); |
||||
|
handleTrack() |
||||
|
} else if (currentIndex.value == 1) { |
||||
|
console.log(index); |
||||
|
handleRadar() |
||||
|
} else if (currentIndex.value == 2) { |
||||
|
console.log(index); |
||||
|
handleDecode() |
||||
|
} else if (currentIndex.value == 3) { |
||||
|
console.log(index); |
||||
|
handleCapitalFlow() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const stockName = ref('') |
||||
|
const searchName = ref('') |
||||
|
const stockCode = ref('') |
||||
|
const language = ref('') |
||||
|
const recordId = ref('') |
||||
|
const parentId = ref('') |
||||
|
const stockId = ref('') |
||||
|
//点击主力追踪 |
||||
|
const handleTrack = async () => { |
||||
|
try { |
||||
|
const result = await getModel1First({ |
||||
|
content: searchName.value, |
||||
|
language: "cn", |
||||
|
marketList: "hk,cn,usa,my,sg,vi,in,gb", |
||||
|
model: 1 |
||||
|
}) |
||||
|
console.log('result', result); |
||||
|
if (result.code == 200) { |
||||
|
stockCode.value = result.data.code |
||||
|
stockName.value = result.data.name |
||||
|
recordId.value = result.data.recordId |
||||
|
parentId.value = result.data.parentId |
||||
|
stockId.value = result.data.stockId |
||||
|
language.value = result.data.language |
||||
|
const res = await getModel1Second({ |
||||
|
language: language.value, |
||||
|
recordId: recordId.value, |
||||
|
parentId: parentId.value, |
||||
|
stockId: stockId.value |
||||
|
}) |
||||
|
console.log('res', res); |
||||
|
} |
||||
|
|
||||
|
} catch { |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//点击主力雷达 |
||||
|
const handleRadar = () => { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
//点击主力解码 |
||||
|
const handleDecode = () => { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
//点击主力资金流 |
||||
|
const handleCapitalFlow = () => { |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
// 1. K线图配置 |
||||
|
const opts = ref({ |
||||
|
rotate: false, |
||||
|
rotateLock: false, |
||||
|
color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4", "#ea7ccc"], |
||||
|
padding: [15, 15, 0, 15], |
||||
|
dataLabel: false, |
||||
|
enableScroll: true, |
||||
|
enableMarkLine: false, |
||||
|
legend: {}, |
||||
|
xAxis: { |
||||
|
labelCount: 4, |
||||
|
itemCount: 30, |
||||
|
disableGrid: true, |
||||
|
gridColor: "#CCCCCC", |
||||
|
gridType: "solid", |
||||
|
dashLength: 4, |
||||
|
scrollShow: false, |
||||
|
scrollAlign: "left", |
||||
|
scrollColor: "#A6A6A6", |
||||
|
scrollBackgroundColor: "#EFEBEF", |
||||
|
labelColor: "#8C8C8C", |
||||
|
fontSize: 9 |
||||
|
}, |
||||
|
yAxis: { |
||||
|
labelColor: "#8C8C8C", |
||||
|
fontSize: 9 |
||||
|
}, |
||||
|
extra: { |
||||
|
candle: { |
||||
|
color: { |
||||
|
upLine: "#f04864", |
||||
|
upFill: "#f04864", |
||||
|
downLine: "#2fc25b", |
||||
|
downFill: "#2fc25b" |
||||
|
}, |
||||
|
average: { |
||||
|
show: false, |
||||
|
name: ["MA5", "MA10", "MA30"], |
||||
|
day: [5, 10, 20], |
||||
|
color: ["#1890ff", "#2fc25b", "#facc14"] |
||||
|
} |
||||
|
}, |
||||
|
markLine: { |
||||
|
type: "dash", |
||||
|
dashLength: 5, |
||||
|
data: [{ |
||||
|
value: 2150, |
||||
|
lineColor: "#f04864", |
||||
|
showLabel: false |
||||
|
}, |
||||
|
{ |
||||
|
value: 2350, |
||||
|
lineColor: "#f04864", |
||||
|
showLabel: false |
||||
|
} |
||||
|
] |
||||
|
}, |
||||
|
tooltip: { |
||||
|
showCategory: true |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// 2. K线图数据(响应式定义) |
||||
|
const chartData = ref({}) |
||||
|
|
||||
|
// 获取K线数据函数(直接定义,无需methods) |
||||
|
const getServerData = () => { |
||||
|
// 模拟服务器请求延时 |
||||
|
setTimeout(() => { |
||||
|
const res = { |
||||
|
"categories": [ |
||||
|
"2025/08/25", |
||||
|
"2025/08/26", |
||||
|
"2025/08/27", |
||||
|
"2025/08/28", |
||||
|
"2025/08/29", |
||||
|
"2025/09/01", |
||||
|
"2025/09/02", |
||||
|
"2025/09/03", |
||||
|
"2025/09/04", |
||||
|
"2025/09/05", |
||||
|
"2025/09/08", |
||||
|
"2025/09/09", |
||||
|
"2025/09/10", |
||||
|
"2025/09/11", |
||||
|
"2025/09/12", |
||||
|
"2025/09/15", |
||||
|
"2025/09/16", |
||||
|
"2025/09/17", |
||||
|
"2025/09/18", |
||||
|
"2025/09/19", |
||||
|
"2025/09/22", |
||||
|
"2025/09/23", |
||||
|
"2025/09/24", |
||||
|
"2025/09/25", |
||||
|
"2025/09/26", |
||||
|
"2025/09/29", |
||||
|
"2025/09/30", |
||||
|
"2025/10/09", |
||||
|
"2025/10/10", |
||||
|
"2025/10/13", |
||||
|
"2025/10/14", |
||||
|
"2025/10/15", |
||||
|
"2025/10/16", |
||||
|
"2025/10/17", |
||||
|
"2025/10/20", |
||||
|
"2025/10/21", |
||||
|
"2025/10/22", |
||||
|
"2025/10/23", |
||||
|
"2025/10/24", |
||||
|
"2025/10/27" |
||||
|
], |
||||
|
series: [{ |
||||
|
"name": "贵州茅台", |
||||
|
"data": [ |
||||
|
[ |
||||
|
1470.01, |
||||
|
1496.0, |
||||
|
1466.0, |
||||
|
1499.33 |
||||
|
], |
||||
|
[ |
||||
|
1490.32, |
||||
|
1474.23, |
||||
|
1480.01, |
||||
|
1481.61 |
||||
|
], |
||||
|
[ |
||||
|
1481.88, |
||||
|
1484.93, |
||||
|
1448.0, |
||||
|
1448.0 |
||||
|
], |
||||
|
[ |
||||
|
1447.97, |
||||
|
1456.1, |
||||
|
1438.77, |
||||
|
1446.1 |
||||
|
], |
||||
|
[ |
||||
|
1453.0, |
||||
|
1482.58, |
||||
|
1452.0, |
||||
|
1480.0 |
||||
|
], |
||||
|
[ |
||||
|
1482.2, |
||||
|
1488.0, |
||||
|
1465.7, |
||||
|
1476.1 |
||||
|
], |
||||
|
[ |
||||
|
1478.66, |
||||
|
1509.0, |
||||
|
1478.0, |
||||
|
1491.3 |
||||
|
], |
||||
|
[ |
||||
|
1491.0, |
||||
|
1503.5, |
||||
|
1466.0, |
||||
|
1480.55 |
||||
|
], |
||||
|
[ |
||||
|
1472.0, |
||||
|
1479.3, |
||||
|
1460.47, |
||||
|
1480.66 |
||||
|
], |
||||
|
[ |
||||
|
1471.0, |
||||
|
1486.97, |
||||
|
1464.0, |
||||
|
1483.0 |
||||
|
], |
||||
|
[ |
||||
|
1483.0, |
||||
|
1506.44, |
||||
|
1477.5, |
||||
|
1501.23 |
||||
|
], |
||||
|
[ |
||||
|
1505.0, |
||||
|
1509.95, |
||||
|
1493.42, |
||||
|
1505.0 |
||||
|
], |
||||
|
[ |
||||
|
1506.66, |
||||
|
1529.95, |
||||
|
1496.0, |
||||
|
1522.01 |
||||
|
], |
||||
|
[ |
||||
|
1522.01, |
||||
|
1526.02, |
||||
|
1508.5, |
||||
|
1523.5 |
||||
|
], |
||||
|
[ |
||||
|
1526.0, |
||||
|
1538.02, |
||||
|
1510.53, |
||||
|
1516.0 |
||||
|
], |
||||
|
[ |
||||
|
1515.87, |
||||
|
1517.48, |
||||
|
1501.5, |
||||
|
1515.1 |
||||
|
], |
||||
|
[ |
||||
|
1515.1, |
||||
|
1520.99, |
||||
|
1496.21, |
||||
|
1499.98 |
||||
|
], |
||||
|
[ |
||||
|
1499.99, |
||||
|
1510.28, |
||||
|
1490.01, |
||||
|
1493.0 |
||||
|
], |
||||
|
[ |
||||
|
1492.0, |
||||
|
1497.8, |
||||
|
1463.5, |
||||
|
1467.96 |
||||
|
], |
||||
|
[ |
||||
|
1467.99, |
||||
|
1475.5, |
||||
|
1457.01, |
||||
|
1467.97 |
||||
|
], |
||||
|
[ |
||||
|
1465.09, |
||||
|
1467.97, |
||||
|
1450.01, |
||||
|
1453.35 |
||||
|
], |
||||
|
[ |
||||
|
1450.5, |
||||
|
1457.5, |
||||
|
1440.0, |
||||
|
1447.42 |
||||
|
], |
||||
|
[ |
||||
|
1434.07, |
||||
|
1456.78, |
||||
|
1434.07, |
||||
|
1442.0 |
||||
|
], |
||||
|
[ |
||||
|
1442.83, |
||||
|
1445.21, |
||||
|
1436.0, |
||||
|
1439.0 |
||||
|
], |
||||
|
[ |
||||
|
1441.18, |
||||
|
1447.11, |
||||
|
1428.01, |
||||
|
1435.0 |
||||
|
], |
||||
|
[ |
||||
|
1439.38, |
||||
|
1469.99, |
||||
|
1435.0, |
||||
|
1460.86 |
||||
|
], |
||||
|
[ |
||||
|
1460.0, |
||||
|
1460.76, |
||||
|
1440.0, |
||||
|
1443.99 |
||||
|
], |
||||
|
[ |
||||
|
1436.0, |
||||
|
1439.38, |
||||
|
1420.0, |
||||
|
1436.78 |
||||
|
], |
||||
|
[ |
||||
|
1437.6, |
||||
|
1439.94, |
||||
|
1427.5, |
||||
|
1430.0 |
||||
|
], |
||||
|
[ |
||||
|
1415.7, |
||||
|
1422.85, |
||||
|
1415.12, |
||||
|
1419.2 |
||||
|
], |
||||
|
[ |
||||
|
1429.99, |
||||
|
1464.0, |
||||
|
1429.99, |
||||
|
1451.02 |
||||
|
], |
||||
|
[ |
||||
|
1450.98, |
||||
|
1463.0, |
||||
|
1445.08, |
||||
|
1462.0 |
||||
|
], |
||||
|
[ |
||||
|
1461.92, |
||||
|
1484.95, |
||||
|
1458.88, |
||||
|
1484.91 |
||||
|
], |
||||
|
[ |
||||
|
1483.1, |
||||
|
1488.0, |
||||
|
1454.03, |
||||
|
1455.0 |
||||
|
], |
||||
|
[ |
||||
|
1455.0, |
||||
|
1469.5, |
||||
|
1454.88, |
||||
|
1457.93 |
||||
|
], |
||||
|
[ |
||||
|
1459.0, |
||||
|
1469.94, |
||||
|
1455.5, |
||||
|
1462.26 |
||||
|
], |
||||
|
[ |
||||
|
1462.08, |
||||
|
1465.73, |
||||
|
1456.0, |
||||
|
1458.7 |
||||
|
], |
||||
|
[ |
||||
|
1455.0, |
||||
|
1468.8, |
||||
|
1447.2, |
||||
|
1467.98 |
||||
|
], |
||||
|
[ |
||||
|
1467.95, |
||||
|
1478.88, |
||||
|
1449.34, |
||||
|
1450.0 |
||||
|
], |
||||
|
[ |
||||
|
1440.0, |
||||
|
1452.49, |
||||
|
1435.99, |
||||
|
1440.41 |
||||
|
] |
||||
|
], |
||||
|
}] |
||||
|
} |
||||
|
// 给响应式变量赋值(需修改.value) |
||||
|
chartData.value = JSON.parse(JSON.stringify(res)) |
||||
|
}, 500) |
||||
|
} |
||||
|
|
||||
|
// 生命周期钩子:组件挂载后执行(替代onReady) |
||||
|
onMounted(() => { |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight |
||||
|
getServerData() // 调用数据获取函数 |
||||
|
}) |
||||
|
|
||||
|
// 页面加载时执行 |
||||
|
onLoad((e) => { |
||||
|
if (e.index) { |
||||
|
currentIndex.value = e.index - 1 |
||||
|
console.log('模块:', currentIndex.value) |
||||
|
} |
||||
|
if (e.stockName) { |
||||
|
stockName.value = e.stockName |
||||
|
console.log('股票名称:', stockName.value) |
||||
|
} |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.main { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
background-color: #fff; |
||||
|
|
||||
|
.search { |
||||
|
position: relative; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
background-color: #F3F3F3; |
||||
|
width: calc(100% - 60rpx); |
||||
|
height: 80rpx; |
||||
|
border-radius: 50rpx; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
||||
|
padding: 0 40rpx; |
||||
|
margin: 15rpx 30rpx 0 30rpx; |
||||
|
|
||||
|
.seachIcon { |
||||
|
position: absolute; |
||||
|
right: 50rpx; |
||||
|
width: 32rpx; |
||||
|
height: 32rpx; |
||||
|
} |
||||
|
|
||||
|
.searchInput { |
||||
|
color: #111; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
margin-top: 30rpx; |
||||
|
padding-top: 30rpx; |
||||
|
background-color: rgb(248, 248, 248); |
||||
|
|
||||
|
.select { |
||||
|
position: relative; |
||||
|
margin-bottom: -5rpx; |
||||
|
|
||||
|
.img { |
||||
|
width: 750rpx; |
||||
|
height: 198rpx; |
||||
|
} |
||||
|
|
||||
|
.selectItem { |
||||
|
.btn { |
||||
|
position: absolute; |
||||
|
width: 120rpx; |
||||
|
height: 150rpx; |
||||
|
background-color: transparent; |
||||
|
|
||||
|
&::after { |
||||
|
border: none; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&:nth-of-type(1) .btn { |
||||
|
top: 30rpx; |
||||
|
left: 60rpx; |
||||
|
} |
||||
|
|
||||
|
&:nth-of-type(2) .btn { |
||||
|
top: 30rpx; |
||||
|
left: 230rpx; |
||||
|
} |
||||
|
|
||||
|
&:nth-of-type(3) .btn { |
||||
|
top: 30rpx; |
||||
|
left: 400rpx; |
||||
|
} |
||||
|
|
||||
|
&:nth-of-type(4) .btn { |
||||
|
top: 30rpx; |
||||
|
left: 570rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.graphAndTxt { |
||||
|
height: 300rpx; |
||||
|
background-color: #fff; |
||||
|
border-radius: 50rpx 50rpx 0 0; |
||||
|
padding: 68.6rpx 36.5rpx 0 36.5rpx; |
||||
|
|
||||
|
.graph { |
||||
|
border: 1rpx solid #e2e2e2; |
||||
|
border-radius: 30rpx 30rpx 0 0; |
||||
|
|
||||
|
.graph_header { |
||||
|
padding: 32rpx 20.5rpx 0 24rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
|
||||
|
.left { |
||||
|
color: #333333; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 15px; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 15px; |
||||
|
} |
||||
|
|
||||
|
.center { |
||||
|
margin-left: 105rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
|
||||
|
text { |
||||
|
width: 160rpx; |
||||
|
height: 36rpx; |
||||
|
padding-left: 10rpx; |
||||
|
color: #000000; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
text-align: center; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 18px; |
||||
|
font-style: normal; |
||||
|
font-weight: 500; |
||||
|
line-height: 18px; |
||||
|
} |
||||
|
|
||||
|
.last { |
||||
|
width: 15rpx; |
||||
|
height: 20rpx; |
||||
|
margin-right: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.next { |
||||
|
width: 15rpx; |
||||
|
height: 20rpx; |
||||
|
margin-left: 30rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.right { |
||||
|
margin-left: 50rpx; |
||||
|
color: #6a6a6a; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 13px; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 15px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.graph_data { |
||||
|
display: flex; |
||||
|
padding: 48rpx 24rpx; |
||||
|
|
||||
|
text { |
||||
|
display: flex; |
||||
|
color: #25ba5d; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 17px; |
||||
|
line-height: 17px; |
||||
|
} |
||||
|
|
||||
|
text:nth-child(2) { |
||||
|
margin-left: 120rpx; |
||||
|
} |
||||
|
|
||||
|
text:nth-child(3) { |
||||
|
margin-left: 150rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.graph_content { |
||||
|
.charts-box { |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.txt { |
||||
|
background-color: #F3F3F3; |
||||
|
margin-top: 48rpx; |
||||
|
border-radius: 30rpx; |
||||
|
|
||||
|
.txtHeader { |
||||
|
padding: 30rpx 24rpx; |
||||
|
|
||||
|
image { |
||||
|
width: 20rpx; |
||||
|
height: 20rpx; |
||||
|
} |
||||
|
|
||||
|
text { |
||||
|
background-color: #FFFFFF; |
||||
|
color: #000000; |
||||
|
padding: 0 22rpx; |
||||
|
border-radius: 22rpx; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 400; |
||||
|
line-height: 37rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.txtContent { |
||||
|
min-height: 200rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
width: 100%; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
* { |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,427 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<!-- 顶部状态栏占位 --> |
||||
|
<view class="top" :style="{height:iSMT+'px'}"></view> |
||||
|
<!-- 标题图标部分 --> |
||||
|
<deepExploration_header></deepExploration_header> |
||||
|
<view class="search"> |
||||
|
<input v-model="stockName" class="searchInput" type="text" placeholder="请输入股票名称、股票代码" |
||||
|
placeholder-style="color: #A6A6A6; font-size: 22rpx;" /> |
||||
|
<image @click="searchStock" class="seachIcon" src="/static/deepExploration-images/search.png" |
||||
|
mode="aspectFill"></image> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 四大功能模块 --> |
||||
|
<view class="select"> |
||||
|
<view class="selectItem" @click="toMain('主力追踪')"> |
||||
|
<image class="img" src="/static/deepExploration-images/icon3.png" mode="aspectFill"></image> |
||||
|
<view class="txt">主力追踪</view> |
||||
|
</view> |
||||
|
<view class="selectItem" @click="toMain('主力雷达')"> |
||||
|
<image class="img" src="/static/deepExploration-images/icon2.png" mode="aspectFill"></image> |
||||
|
<view class="txt">主力雷达</view> |
||||
|
</view> |
||||
|
<view class="selectItem" @click="toMain('主力解码')"> |
||||
|
<image class="img" src="/static/deepExploration-images/icon1.png" mode="aspectFill"></image> |
||||
|
<view class="txt">主力解码</view> |
||||
|
</view> |
||||
|
<view class="selectItem" @click="toMain('主力资金流')"> |
||||
|
<image class="img" src="/static/deepExploration-images/icon4.png" mode="aspectFill"></image> |
||||
|
<view class="txt">主力资金流</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 灰色间隔 --> |
||||
|
<view class="gap"></view> |
||||
|
<!-- 选股策略 --> |
||||
|
<view class="stockSelection"> |
||||
|
<view class="stockSelection_top"> |
||||
|
<view class="txt"> |
||||
|
<text>选股策略</text> |
||||
|
</view> |
||||
|
<view class="viewAll" @click='viewAll'> |
||||
|
<text>查看全部</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="stockSelection_content"> |
||||
|
<view class="selectionItem"> |
||||
|
<view class="header"> |
||||
|
<view class="left"> |
||||
|
<image src="/static/deepExploration-images/plus.png" mode="aspectFill"></image> |
||||
|
<text>抄底卖顶</text> |
||||
|
</view> |
||||
|
<view class="right"> |
||||
|
<image src="/static/deepExploration-images/Americle.png" mode="aspectFill"></image> |
||||
|
<text>美股</text> |
||||
|
</view> |
||||
|
|
||||
|
</view> |
||||
|
<view class="content"> |
||||
|
<view class="contentTitle"> |
||||
|
<view class="contentTitle_name">股票名称</view> |
||||
|
<view class="contentTitle_close">最新收盘价</view> |
||||
|
<view class="contentTitle_price">选股价格</view> |
||||
|
</view> |
||||
|
<view class="contentItem"> |
||||
|
<view class="row" v-for="(item,index) in stockData" :key="index"> |
||||
|
<view class="nameItem">{{item.name}}</view> |
||||
|
<view class="closeItem">{{item.close}}</view> |
||||
|
<view class="priceItem">{{item.select}}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="stockSelection_content"> |
||||
|
<view class="selectionItem"> |
||||
|
<view class="header"> |
||||
|
<view class="left"> |
||||
|
<image src="/static/deepExploration-images/plus.png" mode="aspectFill"></image> |
||||
|
<text>抄底卖顶</text> |
||||
|
</view> |
||||
|
<view class="right"> |
||||
|
<image src="/static/deepExploration-images/Americle.png" mode="aspectFill"></image> |
||||
|
<text>美股</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="content"> |
||||
|
<view class="contentTitle"> |
||||
|
<view class="contentTitle_name">股票名称</view> |
||||
|
<view class="contentTitle_close">最新收盘价</view> |
||||
|
<view class="contentTitle_price">选股价格</view> |
||||
|
</view> |
||||
|
<view class="contentItem"> |
||||
|
<view class="row" v-for="(item,index) in stockData" :key="index"> |
||||
|
<view class="nameItem">{{item.name}}</view> |
||||
|
<view class="closeItem">{{item.close}}</view> |
||||
|
<view class="priceItem">{{item.select}}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
<footerBar class="static-footer" :type="type"></footerBar> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
import footerBar from '@/components/footerBar.vue' |
||||
|
import deepExploration_header from '@/components/deepExploration_header.vue' |
||||
|
|
||||
|
const type = ref('deepExploration') |
||||
|
const iSMT = ref(0) |
||||
|
|
||||
|
//查看全部选股策略 |
||||
|
const toMain = (val) => { |
||||
|
if (val == '主力追踪') { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/deepExploration/MainForceActions?index=1' |
||||
|
}) |
||||
|
} else if (val == '主力雷达') { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/deepExploration/MainForceActions?index=2' |
||||
|
}) |
||||
|
} else if (val == '主力解码') { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/deepExploration/MainForceActions?index=3' |
||||
|
}) |
||||
|
} else if (val == '主力资金流') { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/deepExploration/MainForceActions?index=4' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
const stockName = ref('') |
||||
|
//搜索股票 |
||||
|
const searchStock = () => { |
||||
|
console.log('搜索参数:', stockName.value); |
||||
|
uni.navigateTo({ |
||||
|
url: `/pages/deepExploration/MainForceActions?stockName=${stockName.value}` |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
//查看全部选股策略 |
||||
|
const viewAll = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/deepExploration/stockSelectDetail' |
||||
|
}) |
||||
|
} |
||||
|
//选股策略数据 |
||||
|
const stockData = [{ |
||||
|
name: "(MKTW)MarketWise Inc", |
||||
|
close: "$14.190", |
||||
|
select: "$13.180" |
||||
|
}, |
||||
|
{ |
||||
|
name: "(MTCH)Match Group Inc", |
||||
|
close: "$32.120", |
||||
|
select: "$28.120" |
||||
|
}, |
||||
|
{ |
||||
|
name: "(MKTW)MarketWise Inc", |
||||
|
close: "$14.190", |
||||
|
select: "$13.180" |
||||
|
} |
||||
|
]; |
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.main { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
background-color: #fff; |
||||
|
|
||||
|
.search { |
||||
|
position: relative; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
background-color: #F3F3F3; |
||||
|
width: calc(100% - 60rpx); |
||||
|
height: 80rpx; |
||||
|
border-radius: 50rpx; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
||||
|
padding: 0 40rpx; |
||||
|
margin: 15rpx 30rpx 0 30rpx; |
||||
|
|
||||
|
.seachIcon { |
||||
|
position: absolute; |
||||
|
right: 50rpx; |
||||
|
width: 32rpx; |
||||
|
height: 32rpx; |
||||
|
} |
||||
|
|
||||
|
.searchInput { |
||||
|
color: #111; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.select { |
||||
|
display: flex; |
||||
|
padding: 60rpx 10rpx 30rpx 30rpx; |
||||
|
gap: 70rpx; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
|
||||
|
.selectItem { |
||||
|
.img { |
||||
|
width: 80rpx; |
||||
|
height: 80rpx; |
||||
|
display: block; |
||||
|
margin: 0 auto; |
||||
|
} |
||||
|
|
||||
|
.txt { |
||||
|
color: #6a6a6a; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 11px; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 14.5px; |
||||
|
margin-top: 13rpx; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.gap { |
||||
|
width: 100%; |
||||
|
height: 15rpx; |
||||
|
background-color: #F3F3F3; |
||||
|
} |
||||
|
|
||||
|
.stockSelection { |
||||
|
width: 100%; |
||||
|
padding: 32rpx 15rpx; |
||||
|
|
||||
|
.stockSelection_top { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
|
||||
|
.txt { |
||||
|
color: #000000; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 38rpx; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.viewAll { |
||||
|
background-color: #000000; |
||||
|
border-radius: 10rpx; |
||||
|
padding: 6rpx 20rpx; |
||||
|
color: #ffffff; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 10rpx; |
||||
|
font-style: normal; |
||||
|
font-weight: 100; |
||||
|
line-height: 29rpx; |
||||
|
height: 40rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.stockSelection_content { |
||||
|
.selectionItem { |
||||
|
background-color: #F3F3F3; |
||||
|
padding: 30rpx 15rpx 17rpx 30rpx; |
||||
|
border-radius: 30rpx; |
||||
|
margin-top: 30rpx; |
||||
|
|
||||
|
.header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
|
||||
|
.left { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
|
||||
|
image { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
width: 15rpx; |
||||
|
height: 15rpx; |
||||
|
} |
||||
|
|
||||
|
text { |
||||
|
margin-left: 15rpx; |
||||
|
color: #000000; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 28rpx; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 18.5px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.right { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
border-radius: 15rpx; |
||||
|
background-color: #FFFFFF; |
||||
|
padding: 6rpx 20rpx; |
||||
|
|
||||
|
image { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
width: 40rpx; |
||||
|
height: 26.5rpx; |
||||
|
} |
||||
|
|
||||
|
text { |
||||
|
margin-left: 10rpx; |
||||
|
color: #6a6a6a; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 18rpx; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 24rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
.contentTitle { |
||||
|
display: flex; |
||||
|
color: #6a6a6a; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 11px; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 14.5px; |
||||
|
margin-top: 24rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
|
||||
|
.contentTitle_name { |
||||
|
width: 100rpx; |
||||
|
} |
||||
|
|
||||
|
.contentTitle_close { |
||||
|
width: 130rpx; |
||||
|
margin-left: 260rpx; |
||||
|
} |
||||
|
|
||||
|
.contentTitle_price { |
||||
|
width: 120rpx; |
||||
|
margin-left: 60rpx; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.contentItem { |
||||
|
.row { |
||||
|
display: flex; |
||||
|
box-shadow: 0 -2rpx 5rpx rgba(0, 0, 0, 0.05); |
||||
|
padding: 10rpx 0; |
||||
|
margin-bottom: 10rpx; |
||||
|
|
||||
|
.nameItem { |
||||
|
width: 260rpx; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
color: #000000; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 13px; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 17.5px; |
||||
|
} |
||||
|
|
||||
|
.closeItem { |
||||
|
width: 120rpx; |
||||
|
margin-left: 100rpx; |
||||
|
color: #25ba5d; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 13px; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 17.5px; |
||||
|
} |
||||
|
|
||||
|
.priceItem { |
||||
|
width: 120rpx; |
||||
|
margin-left: 73rpx; |
||||
|
color: #25ba5d; |
||||
|
font-family: "PingFang SC"; |
||||
|
font-size: 13px; |
||||
|
font-style: normal; |
||||
|
font-weight: 400; |
||||
|
line-height: 17.5px; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
* { |
||||
|
box-sizing: border-box; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,354 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view class="table"> |
||||
|
<view class="tableHeader"> |
||||
|
<scroll-view class="tabs" scroll-x="true"> |
||||
|
<view v-for="(item,index) in tabsData" :key="index" class="tabItem" @click="handleTab(item)"> |
||||
|
{{item}} |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
<view class="tableContent"> |
||||
|
<image class="showAll" src="/static/deepExploration-images/showAll.png" mode="aspectFill"></image> |
||||
|
<scroll-view scroll-x="true" show-scrollbar="false"> |
||||
|
<view class="tableBox"> |
||||
|
<view class="box_header"> |
||||
|
<view class="name">名称</view> |
||||
|
<view class="other" v-for="(item,index) in tableContentHeaderData" :key="index"> |
||||
|
<text>{{item}}</text> |
||||
|
<image v-show="ifASC" src="/static/deepExploration-images/ASC.png" mode="aspectFill"> |
||||
|
</image> |
||||
|
<image v-show="!ifASC" src="/static/deepExploration-images/DESC.png" mode="aspectFill"> |
||||
|
</image> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="box_content"> |
||||
|
<view class="row" v-for="(item,index) in fakeData" :key="index" :class="{ 'increase-positive': item.increase.startsWith('+'), |
||||
|
'increase-negative': item.increase.startsWith('-')}"> |
||||
|
<view class="name_colum"> |
||||
|
<text class="stockName">{{item.name}}</text> |
||||
|
<text class="stockCode">{{item.stockCode}}</text> |
||||
|
</view> |
||||
|
<view class="other_colum">{{item.latest}}</view> |
||||
|
<view class="other_colum">{{item.increase}}</view> |
||||
|
<view class="other_colum">{{item.decrease}}</view> |
||||
|
<view class="other_colum">{{item.previousClose}}</view> |
||||
|
<view class="other_colum">{{item.volume}}</view> |
||||
|
<view class="other_colum">{{item.turnover}}</view> |
||||
|
<view class="other_colum">{{item.openingPrice}}</view> |
||||
|
<view class="other_colum">{{item.highestPrice}}</view> |
||||
|
<view class="other_colum">{{item.lowestPrice}}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref |
||||
|
} from 'vue' |
||||
|
|
||||
|
const tabsData = ref(['全部', '抄底卖顶', '波段行情', '价值投资', '资金及仓位管理', '价值投资', '价值投资', '价值投资', ]) |
||||
|
const handleTab = (item) => { |
||||
|
uni.showToast({ |
||||
|
title: `查看 ${item} 详情`, |
||||
|
icon: 'none', |
||||
|
duration: 2000 |
||||
|
}) |
||||
|
} |
||||
|
//表头是否升序 |
||||
|
const ifASC = ref(true) |
||||
|
//表头数据 |
||||
|
const tableContentHeaderData = ref(['最新', '涨幅', '跌幅', '昨收', '成交量', '成交额', '开盘价', '最高价', '最低价']) |
||||
|
const fakeData = [{ |
||||
|
name: "TechCore", |
||||
|
stockCode: "600001", |
||||
|
latest: 1315.00, |
||||
|
increase: "+5.2%", |
||||
|
decrease: "+5.2%", |
||||
|
previousClose: 1250.00, |
||||
|
volume: 12000, |
||||
|
turnover: "15780K", |
||||
|
openingPrice: 1237.50, |
||||
|
highestPrice: 1320.00, |
||||
|
lowestPrice: 1230.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "MediaLink", |
||||
|
stockCode: "600002", |
||||
|
latest: 1138.70, |
||||
|
increase: "-3.5%", |
||||
|
decrease: "-3.5%", |
||||
|
previousClose: 1180.00, |
||||
|
volume: 8500, |
||||
|
turnover: "967.9K", |
||||
|
openingPrice: 1191.80, |
||||
|
highestPrice: 1195.00, |
||||
|
lowestPrice: 1130.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "FinServ", |
||||
|
stockCode: "600003", |
||||
|
latest: 1413.72, |
||||
|
increase: "+7.1%", |
||||
|
decrease: "+7.1%", |
||||
|
previousClose: 1320.00, |
||||
|
volume: 15000, |
||||
|
turnover: "2120.6K", |
||||
|
openingPrice: 1293.60, |
||||
|
highestPrice: 1420.00, |
||||
|
lowestPrice: 1290.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "AutoDrive", |
||||
|
stockCode: "600004", |
||||
|
latest: 1080.40, |
||||
|
increase: "+2.8%", |
||||
|
decrease: "+2.8%", |
||||
|
previousClose: 1050.00, |
||||
|
volume: 9000, |
||||
|
turnover: "972.4K", |
||||
|
openingPrice: 1055.25, |
||||
|
highestPrice: 1085.00, |
||||
|
lowestPrice: 1050.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "EduSmart", |
||||
|
stockCode: "600005", |
||||
|
latest: 968.24, |
||||
|
increase: "-1.2%", |
||||
|
decrease: "-1.2%", |
||||
|
previousClose: 980.00, |
||||
|
volume: 7000, |
||||
|
turnover: "677.8K", |
||||
|
openingPrice: 975.10, |
||||
|
highestPrice: 978.00, |
||||
|
lowestPrice: 965.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "HealthPlusqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", |
||||
|
stockCode: "600006", |
||||
|
latest: 1463.00, |
||||
|
increase: "+4.5%", |
||||
|
decrease: "+4.5%", |
||||
|
previousClose: 1400.00, |
||||
|
volume: 13000, |
||||
|
turnover: "1901.9K", |
||||
|
openingPrice: 1393.00, |
||||
|
highestPrice: 1470.00, |
||||
|
lowestPrice: 1385.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "AgriTech", |
||||
|
stockCode: "600007", |
||||
|
latest: 1038.36, |
||||
|
increase: "+1.8%", |
||||
|
decrease: "+1.8%", |
||||
|
previousClose: 1020.00, |
||||
|
volume: 6500, |
||||
|
turnover: "674.9K", |
||||
|
openingPrice: 1028.16, |
||||
|
highestPrice: 1040.00, |
||||
|
lowestPrice: 1025.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "LogiFlow", |
||||
|
stockCode: "600008", |
||||
|
latest: 1094.24, |
||||
|
increase: "-2.3%", |
||||
|
decrease: "-2.3%", |
||||
|
previousClose: 1120.00, |
||||
|
volume: 8000, |
||||
|
turnover: "875.4K", |
||||
|
openingPrice: 1122.24, |
||||
|
highestPrice: 1125.00, |
||||
|
lowestPrice: 1090.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "EnergySol", |
||||
|
stockCode: "600009", |
||||
|
latest: 1435.05, |
||||
|
increase: "+6.3%", |
||||
|
decrease: "+6.3%", |
||||
|
previousClose: 1350.00, |
||||
|
volume: 14000, |
||||
|
turnover: "2009.1K", |
||||
|
openingPrice: 1339.75, |
||||
|
highestPrice: 1440.00, |
||||
|
lowestPrice: 1335.00 |
||||
|
}, |
||||
|
{ |
||||
|
name: "RealEstate", |
||||
|
stockCode: "600010", |
||||
|
latest: 995.00, |
||||
|
increase: "-0.5%", |
||||
|
decrease: "-0.5%", |
||||
|
previousClose: 1000.00, |
||||
|
volume: 7500, |
||||
|
turnover: "746.3K", |
||||
|
openingPrice: 1003.00, |
||||
|
highestPrice: 1005.00, |
||||
|
lowestPrice: 990.00 |
||||
|
} |
||||
|
]; |
||||
|
</script> |
||||
|
|
||||
|
<style scoped lang="scss"> |
||||
|
.main { |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
background-color: #fff; |
||||
|
|
||||
|
|
||||
|
.table { |
||||
|
margin-top: 10rpx; |
||||
|
box-shadow: 0 -2rpx 3rpx -1rpx rgba(0, 0, 0, 0.5); |
||||
|
|
||||
|
.tableHeader { |
||||
|
.tabs { |
||||
|
white-space: nowrap; |
||||
|
padding-top: 20rpx; |
||||
|
padding-left: 40rpx; |
||||
|
|
||||
|
::-webkit-scrollbar { |
||||
|
//隐藏 滚动条 |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
.tabItem { |
||||
|
display: inline-block; |
||||
|
color: rgb(175, 175, 175); |
||||
|
border-radius: 10rpx; |
||||
|
padding: 5rpx 30rpx; |
||||
|
margin-right: 20rpx; |
||||
|
font-size: 28rpx; |
||||
|
background-color: rgb(243, 243, 243); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.tableContent { |
||||
|
width: 100%; |
||||
|
|
||||
|
position: relative; |
||||
|
|
||||
|
.showAll { |
||||
|
position: absolute; |
||||
|
top: 35rpx; |
||||
|
right: 20rpx; |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
z-index: 100; |
||||
|
} |
||||
|
|
||||
|
scroll-view { |
||||
|
width: 100%; |
||||
|
white-space: nowrap; |
||||
|
|
||||
|
::-webkit-scrollbar { |
||||
|
//隐藏 滚动条 |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
.tableBox { |
||||
|
padding-left: 40rpx; |
||||
|
|
||||
|
.box_header { |
||||
|
margin-bottom: 19rpx; |
||||
|
display: flex; |
||||
|
width: max-content; |
||||
|
margin-top: 40rpx; |
||||
|
color: rgb(109, 109, 109); |
||||
|
border-radius: 10rpx; |
||||
|
margin-right: 20rpx; |
||||
|
font-size: 23rpx; |
||||
|
|
||||
|
|
||||
|
.name { |
||||
|
flex: 0 0 375rpx; |
||||
|
} |
||||
|
|
||||
|
.other { |
||||
|
flex: 0 0 195rpx; |
||||
|
|
||||
|
text { |
||||
|
margin-right: 5rpx; |
||||
|
} |
||||
|
|
||||
|
image { |
||||
|
width: 20rpx; |
||||
|
height: 20rpx; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.box_content { |
||||
|
width: max-content; |
||||
|
|
||||
|
.row { |
||||
|
padding: 5rpx; |
||||
|
display: flex; |
||||
|
border-top: 1rpx dashed #eee; |
||||
|
width: 210%; |
||||
|
|
||||
|
&.increase-positive { |
||||
|
.other_colum { |
||||
|
color: #2DD357; |
||||
|
font-weight: 200; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&.increase-negative { |
||||
|
.other_colum { |
||||
|
color: #FF4150; |
||||
|
font-weight: 200; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.name_colum { |
||||
|
flex: 0 0 375rpx; |
||||
|
|
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
gap: 4rpx; |
||||
|
|
||||
|
.stockName { |
||||
|
color: #333333; |
||||
|
width: 100%; |
||||
|
max-width: 305rpx; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 400; |
||||
|
line-height: 36rpx; |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
} |
||||
|
|
||||
|
.stockCode { |
||||
|
color: #c5c5c5; |
||||
|
; |
||||
|
font-size: 24rpx; |
||||
|
font-weight: 400; |
||||
|
line-height: 30rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.other_colum { |
||||
|
flex: 0 0 195rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
||||
1733
pages/deepMate/deepMate.vue
File diff suppressed because it is too large
View File
@ -1,28 +0,0 @@ |
|||||
<template> |
|
||||
<view class="main"> |
|
||||
<!-- 顶部状态栏占位 --> |
|
||||
<view class="top" :style="{height:iSMT+'px'}"></view> |
|
||||
<view>深度探索</view> |
|
||||
<footerBar class="static-footer" :type="type"></footerBar> |
|
||||
</view> |
|
||||
</template> |
|
||||
|
|
||||
<script setup> |
|
||||
import { ref,onMounted } from 'vue' |
|
||||
import footerBar from '../../components/footerBar.vue' |
|
||||
|
|
||||
const type = ref('deepExploration') |
|
||||
const iSMT = ref(0) |
|
||||
|
|
||||
onMounted(() => { |
|
||||
// 状态栏高度 |
|
||||
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
|
||||
}) |
|
||||
</script> |
|
||||
|
|
||||
<style scoped> |
|
||||
.static-footer { |
|
||||
position: fixed; |
|
||||
bottom: 0; |
|
||||
} |
|
||||
</style> |
|
||||
1214
pages/home/home.vue
File diff suppressed because it is too large
View File
@ -1,28 +1,294 @@ |
|||||
<template> |
<template> |
||||
<view class="main"> |
<view class="main"> |
||||
<!-- 顶部状态栏占位 --> |
|
||||
<view class="top" :style="{height:iSMT+'px'}"></view> |
|
||||
<view>我的</view> |
|
||||
|
<view class="top"> |
||||
|
<view class="bell"> |
||||
|
<image class="image-bell" src="/static/my/bell.png"></image> |
||||
|
</view> |
||||
|
<view class="msg"> |
||||
|
<view class="msg-left"> |
||||
|
<view class="avatar"></view> |
||||
|
</view> |
||||
|
<view class="msg-center"> |
||||
|
<view style="display: flex;"> |
||||
|
<view class="userInfo">{{ username }}</view> |
||||
|
<image class="image-editName" src="/static/my/editName.png"></image> |
||||
|
</view> |
||||
|
<view class="userId">ID:{{ dccode }}</view> |
||||
|
</view> |
||||
|
<view class="msg-right"> |
||||
|
<image class="image-attendance" src="/static/my/Check-in.png" /> |
||||
|
<span style="font-size:10px;">签到</span> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="settings-buttons"> |
||||
|
<view class="setting-btn" @click="goToMarket"> |
||||
|
<image src="/static/my/MarketSettings.png" class="setting-icon" /> |
||||
|
<text>行情设置</text> |
||||
|
</view> |
||||
|
<view class="setting-btn" @click="goToGeneral"> |
||||
|
<image src="/static/my/Settings.png" class="setting-icon" /> |
||||
|
<text>通用设置</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="share" @click="goToShare"> |
||||
|
<image class="img-share" src="/static/my/share.png" mode="widthFix" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="bottom"> |
||||
|
<view class="list-item" @click="goToAccount"> |
||||
|
<image src="/static/my/security.png" class="list-icon" /> |
||||
|
<text>账号与安全</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
<view class="list-item"> |
||||
|
<image src="/static/my/connection.png" class="list-icon" /> |
||||
|
<text>联系我们</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
<view class="list-item" @click="goToNewVersion"> |
||||
|
<image src="/static/my/update.png" class="list-icon" /> |
||||
|
<text>新版本更新</text> |
||||
|
<view class="update-tip">有新版本可更新 |
||||
|
<view class="circle"></view> |
||||
|
</view> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
<view class="list-item"> |
||||
|
<image src="/static/my/opinion.png" class="list-icon" /> |
||||
|
<text>意见反馈</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
<view class="list-item" @click="goToAbout"> |
||||
|
<image src="/static/my/about.png" class="list-icon" /> |
||||
|
<text>关于DeepChart</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
</view> |
||||
<footerBar class="static-footer" :type="type"></footerBar> |
<footerBar class="static-footer" :type="type"></footerBar> |
||||
</view> |
</view> |
||||
</template> |
</template> |
||||
|
|
||||
<script setup> |
<script setup> |
||||
import { ref,onMounted } from 'vue' |
|
||||
import footerBar from '../../components/footerBar.vue' |
|
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
import { |
||||
|
ArrowRight |
||||
|
} from '@element-plus/icons-vue' |
||||
|
import footerBar from '../../components/footerBar.vue' |
||||
|
|
||||
|
const type = ref('member') |
||||
|
const iSMT = ref(0) |
||||
|
const username = ref('演示机EVA') |
||||
|
const dccode = ref('90047681') |
||||
|
const goToGeneral = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/setting/general' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToMarket = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '../setting/market' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
const type = ref('member') |
|
||||
const iSMT = ref(0) |
|
||||
|
const goToAccount = () => { |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/account' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
onMounted(() => { |
|
||||
// 状态栏高度 |
|
||||
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
|
||||
}) |
|
||||
|
const goToNewVersion = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/newVersion' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToAbout = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/about' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToShare = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/share' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight |
||||
|
console.log('??????????????', iSMT.value) |
||||
|
}) |
||||
</script> |
</script> |
||||
|
|
||||
<style scoped> |
<style scoped> |
||||
.static-footer { |
|
||||
position: fixed; |
|
||||
bottom: 0; |
|
||||
} |
|
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
|
||||
|
.top { |
||||
|
height: 47vh; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.bell { |
||||
|
height: 9.6vh; |
||||
|
display: flex; |
||||
|
align-items: flex-end; |
||||
|
justify-content: flex-end; |
||||
|
padding-right: 50rpx; |
||||
|
} |
||||
|
|
||||
|
.image-bell { |
||||
|
width: 13px; |
||||
|
height: 16px; |
||||
|
} |
||||
|
|
||||
|
.msg { |
||||
|
height: 10.7vh; |
||||
|
display: flex; |
||||
|
margin-top: 3vh; |
||||
|
margin-bottom: 3vh; |
||||
|
} |
||||
|
|
||||
|
.msg-left { |
||||
|
width: 33.6vw; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.avatar { |
||||
|
width: 175rpx; |
||||
|
height: 175rpx; |
||||
|
border-radius: 50%; |
||||
|
background-color: black; |
||||
|
} |
||||
|
|
||||
|
.msg-center { |
||||
|
width: 51.7vw; |
||||
|
padding-left: 2.5vh; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.userInfo { |
||||
|
font-size: 20px; |
||||
|
} |
||||
|
|
||||
|
.userId { |
||||
|
font-size: 14px; |
||||
|
margin-top: 1vh; |
||||
|
} |
||||
|
|
||||
|
.image-editName { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
margin-left: 2vw; |
||||
|
} |
||||
|
|
||||
|
.msg-right { |
||||
|
width: 14.7vw; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.image-attendance { |
||||
|
width: 43rpx; |
||||
|
height: 43rpx; |
||||
|
} |
||||
|
|
||||
|
.settings-buttons { |
||||
|
display: flex; |
||||
|
justify-content: space-around; |
||||
|
} |
||||
|
|
||||
|
.setting-btn { |
||||
|
width: 349rpx; |
||||
|
height: 135rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
background-color: rgb(243, 243, 243); |
||||
|
border-radius: 8%; |
||||
|
} |
||||
|
|
||||
|
.setting-icon { |
||||
|
width: 64.7rpx; |
||||
|
height: 64.7rpx; |
||||
|
margin-right: 25rpx; |
||||
|
} |
||||
|
|
||||
|
.setting-btn text { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.share { |
||||
|
height: 12.6vh; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.img-share { |
||||
|
width: 720rpx; |
||||
|
height: 160rpx; |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 44.5vh; |
||||
|
margin-top: 1vh; |
||||
|
background-color: rgb(255, 255, 255); |
||||
|
} |
||||
|
|
||||
|
.list-item { |
||||
|
width: 670rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin: 0rpx 40rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.list-item:last-child{ |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.list-icon { |
||||
|
width: 42rpx; |
||||
|
height: 42rpx; |
||||
|
margin-right: 18rpx; |
||||
|
} |
||||
|
|
||||
|
.arrow { |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
|
||||
|
.update-tip { |
||||
|
display: flex; |
||||
|
color: #999; |
||||
|
font-size: 24rpx; |
||||
|
align-items: center; |
||||
|
margin-left: 200rpx; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.circle { |
||||
|
width: 10rpx; |
||||
|
height: 10rpx; |
||||
|
border-radius: 50%; |
||||
|
background-color: red; |
||||
|
margin-left: 10rpx; |
||||
|
} |
||||
</style> |
</style> |
||||
@ -0,0 +1,655 @@ |
|||||
|
<template> |
||||
|
<view style="width: 750rpx; height: 750rpx;"> |
||||
|
<l-echart ref="chartRef" @finished="initChart"></l-echart> |
||||
|
</view> |
||||
|
</template> |
||||
|
<script setup> |
||||
|
import { ref, computed, onMounted } from 'vue'; |
||||
|
|
||||
|
const chartRef = ref(null) |
||||
|
// 获取系统信息,替代 window.innerWidth |
||||
|
const systemInfo = uni.getSystemInfoSync() |
||||
|
const screenWidth = ref(systemInfo.screenWidth || 375) // 默认值 375px |
||||
|
|
||||
|
// 生成30天的交易信号数据 |
||||
|
const generateAIGoldBullData = () => { |
||||
|
const data = [] |
||||
|
|
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
// 模拟交易信号 [索引, 买入信号, 卖出信号, 持有信号, 强度, 成交量] |
||||
|
const buySignal = Math.random() > 0.7 ? 1 : 0 // 30%概率买入信号 |
||||
|
const sellSignal = Math.random() > 0.8 ? 1 : 0 // 20%概率卖出信号 |
||||
|
const holdSignal = Math.random() > 0.5 ? 1 : 0 // 50%概率持有信号 |
||||
|
const strength = Math.floor(Math.random() * 3) + 1 // 信号强度1-3 |
||||
|
const volume = Math.floor(Math.random() * 2000) + 500 // 成交量500-2500 |
||||
|
|
||||
|
data.push([i, buySignal, sellSignal, holdSignal, strength, volume]) |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 添加缺失的变量定义 |
||||
|
var option |
||||
|
const AIGoldBull = ref({ |
||||
|
JN: generateAIGoldBullData() |
||||
|
}) |
||||
|
|
||||
|
// 模拟多语言数据 |
||||
|
const t = ref({ |
||||
|
suoxie: 'zh', |
||||
|
tianxian: '天线', |
||||
|
feixian: '飞线', |
||||
|
zhoongxian: '中线', |
||||
|
liuxian: '流线', |
||||
|
Klinetext_5: 'K线5', |
||||
|
Klinetext_6: 'K线6', |
||||
|
maipan: '买盘', |
||||
|
maipan1: '卖盘' |
||||
|
}) |
||||
|
|
||||
|
// 生成30天的模拟K线数据 [日期, 开盘, 最高, 最低, 收盘] |
||||
|
const generateKLineData = () => { |
||||
|
const data = [] |
||||
|
let basePrice = 2450 // 黄金基础价格 |
||||
|
|
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
const date = new Date(2024, 0, i + 1).toISOString().split('T')[0] |
||||
|
|
||||
|
// 模拟价格波动 |
||||
|
const volatility = (Math.random() - 0.5) * 50 // ±25的波动 |
||||
|
const open = basePrice + volatility |
||||
|
|
||||
|
const highVolatility = Math.random() * 30 + 10 // 10-40的向上波动 |
||||
|
const lowVolatility = Math.random() * 30 + 10 // 10-40的向下波动 |
||||
|
|
||||
|
const high = Math.max(open, open + highVolatility) |
||||
|
const low = Math.min(open, open - lowVolatility) |
||||
|
|
||||
|
const closeVolatility = (Math.random() - 0.5) * 20 |
||||
|
const close = Math.max(low, Math.min(high, open + closeVolatility)) |
||||
|
|
||||
|
data.push([date, |
||||
|
Math.round(open * 100) / 100, |
||||
|
Math.round(high * 100) / 100, |
||||
|
Math.round(low * 100) / 100, |
||||
|
Math.round(close * 100) / 100 |
||||
|
]) |
||||
|
|
||||
|
basePrice = close // 下一天的基础价格 |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 生成30天的成交量和技术指标数据 [日期, 成交量1, 成交量2, 指标1, 指标2, 指标3] |
||||
|
const generateWaveVolData = () => { |
||||
|
const data = [] |
||||
|
|
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
const date = new Date(2024, 0, i + 1).toISOString().split('T')[0] |
||||
|
|
||||
|
// 模拟成交量数据 |
||||
|
const vol1 = Math.floor(Math.random() * 2000) + 800 // 800-2800 |
||||
|
const vol2 = Math.floor(Math.random() * 1500) + 600 // 600-2100 |
||||
|
|
||||
|
// 模拟技术指标 |
||||
|
const indicator1 = Math.floor(Math.random() * 30) + 40 // 40-70 |
||||
|
const indicator2 = Math.floor(Math.random() * 40) + 50 // 50-90 |
||||
|
const indicator3 = Math.floor(Math.random() * 35) + 60 // 60-95 |
||||
|
|
||||
|
data.push([date, vol1, vol2, indicator1, indicator2, indicator3]) |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 生成30天的移动平均线数据 [MA5, MA10, MA20, MA30] |
||||
|
const generateFTLineData = () => { |
||||
|
const data = [] |
||||
|
let ma5Base = 2450 |
||||
|
let ma10Base = 2445 |
||||
|
let ma20Base = 2440 |
||||
|
let ma30Base = 2435 |
||||
|
|
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
// 模拟移动平均线的平滑变化 |
||||
|
ma5Base += (Math.random() - 0.5) * 10 |
||||
|
ma10Base += (Math.random() - 0.5) * 8 |
||||
|
ma20Base += (Math.random() - 0.5) * 6 |
||||
|
ma30Base += (Math.random() - 0.5) * 4 |
||||
|
|
||||
|
data.push([ |
||||
|
Math.round(ma5Base * 100) / 100, |
||||
|
Math.round(ma10Base * 100) / 100, |
||||
|
Math.round(ma20Base * 100) / 100, |
||||
|
Math.round(ma30Base * 100) / 100 |
||||
|
]) |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 生成模拟数据 |
||||
|
const mockKLineData = generateKLineData() |
||||
|
const mockWaveVolData = generateWaveVolData() |
||||
|
const mockFTLineData = generateFTLineData() |
||||
|
|
||||
|
// 生成RSI指标数据 (相对强弱指数) |
||||
|
const generateRSIData = () => { |
||||
|
const data = [] |
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
const rsi = Math.random() * 60 + 20 // RSI值在20-80之间 |
||||
|
data.push(Math.round(rsi * 100) / 100) |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 生成MACD指标数据 |
||||
|
const generateMACDData = () => { |
||||
|
const data = [] |
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
const macd = (Math.random() - 0.5) * 20 // MACD值在-10到10之间 |
||||
|
const signal = (Math.random() - 0.5) * 15 // 信号线 |
||||
|
const histogram = macd - signal // 柱状图 |
||||
|
|
||||
|
data.push([ |
||||
|
Math.round(macd * 100) / 100, |
||||
|
Math.round(signal * 100) / 100, |
||||
|
Math.round(histogram * 100) / 100 |
||||
|
]) |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 生成布林带数据 |
||||
|
const generateBollingerData = () => { |
||||
|
const data = [] |
||||
|
let middleLine = 2450 |
||||
|
|
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
middleLine += (Math.random() - 0.5) * 10 |
||||
|
const upperBand = middleLine + Math.random() * 30 + 20 // 上轨 |
||||
|
const lowerBand = middleLine - Math.random() * 30 - 20 // 下轨 |
||||
|
|
||||
|
data.push([ |
||||
|
Math.round(upperBand * 100) / 100, |
||||
|
Math.round(middleLine * 100) / 100, |
||||
|
Math.round(lowerBand * 100) / 100 |
||||
|
]) |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 生成成交量分析数据 |
||||
|
const generateVolumeAnalysisData = () => { |
||||
|
const data = [] |
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
const buyVolume = Math.floor(Math.random() * 1500) + 500 // 买入量 |
||||
|
const sellVolume = Math.floor(Math.random() * 1500) + 500 // 卖出量 |
||||
|
const netVolume = buyVolume - sellVolume // 净买入量 |
||||
|
|
||||
|
data.push([buyVolume, sellVolume, netVolume]) |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 生成市场情绪数据 |
||||
|
const generateMarketSentimentData = () => { |
||||
|
const sentiments = ['极度恐慌', '恐慌', '中性', '贪婪', '极度贪婪'] |
||||
|
const data = [] |
||||
|
|
||||
|
for (let i = 0; i < 30; i++) { |
||||
|
const sentimentIndex = Math.floor(Math.random() * 100) // 0-100的情绪指数 |
||||
|
const sentimentLabel = sentiments[Math.floor(sentimentIndex / 20)] |
||||
|
|
||||
|
data.push({ |
||||
|
date: new Date(2024, 0, i + 1).toISOString().split('T')[0], |
||||
|
index: sentimentIndex, |
||||
|
label: sentimentLabel, |
||||
|
fearGreedRatio: Math.random() * 100 |
||||
|
}) |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 生成重要新闻事件数据 |
||||
|
const generateNewsEventsData = () => { |
||||
|
const events = [ |
||||
|
'美联储利率决议', |
||||
|
'非农就业数据发布', |
||||
|
'通胀数据公布', |
||||
|
'地缘政治紧张', |
||||
|
'央行政策变化', |
||||
|
'经济数据超预期', |
||||
|
'市场技术突破', |
||||
|
'大宗商品价格波动' |
||||
|
] |
||||
|
|
||||
|
const data = [] |
||||
|
for (let i = 0; i < 10; i++) { // 生成10个随机事件 |
||||
|
const randomDay = Math.floor(Math.random() * 30) + 1 |
||||
|
const event = events[Math.floor(Math.random() * events.length)] |
||||
|
const impact = Math.floor(Math.random() * 5) + 1 // 影响力1-5 |
||||
|
|
||||
|
data.push({ |
||||
|
date: new Date(2024, 0, randomDay).toISOString().split('T')[0], |
||||
|
event: event, |
||||
|
impact: impact, |
||||
|
type: Math.random() > 0.5 ? 'positive' : 'negative' |
||||
|
}) |
||||
|
} |
||||
|
return data.sort((a, b) => new Date(a.date) - new Date(b.date)) |
||||
|
} |
||||
|
|
||||
|
// 生成价格预测数据 |
||||
|
const generatePricePredictionData = () => { |
||||
|
const data = [] |
||||
|
let currentPrice = 2450 |
||||
|
|
||||
|
for (let i = 0; i < 7; i++) { // 未来7天预测 |
||||
|
const date = new Date(2024, 1, i + 1).toISOString().split('T')[0] // 2月份 |
||||
|
|
||||
|
// 模拟AI预测的价格区间 |
||||
|
const prediction = currentPrice + (Math.random() - 0.5) * 100 |
||||
|
const confidence = Math.random() * 40 + 60 // 60-100%的置信度 |
||||
|
const upperBound = prediction + Math.random() * 50 |
||||
|
const lowerBound = prediction - Math.random() * 50 |
||||
|
|
||||
|
data.push({ |
||||
|
date: date, |
||||
|
predicted_price: Math.round(prediction * 100) / 100, |
||||
|
confidence: Math.round(confidence), |
||||
|
upper_bound: Math.round(upperBound * 100) / 100, |
||||
|
lower_bound: Math.round(lowerBound * 100) / 100 |
||||
|
}) |
||||
|
|
||||
|
currentPrice = prediction |
||||
|
} |
||||
|
return data |
||||
|
} |
||||
|
|
||||
|
// 模拟提取的绘图数据 |
||||
|
const extractedDrawData = { |
||||
|
KLine20: mockKLineData, |
||||
|
WAVEVOL: mockWaveVolData, |
||||
|
FTLINE: mockFTLineData, |
||||
|
RSI: generateRSIData(), |
||||
|
MACD: generateMACDData(), |
||||
|
BOLLINGER: generateBollingerData(), |
||||
|
VOLUME_ANALYSIS: generateVolumeAnalysisData(), |
||||
|
MARKET_SENTIMENT: generateMarketSentimentData(), |
||||
|
NEWS_EVENTS: generateNewsEventsData(), |
||||
|
PRICE_PREDICTION: generatePricePredictionData() |
||||
|
} |
||||
|
|
||||
|
const fnShowEcharts4 = (extractedDrawData) => { |
||||
|
const splitData = (b) => { |
||||
|
const a = JSON.parse(JSON.stringify(b)) |
||||
|
let categoryData = [] |
||||
|
let values = [] |
||||
|
for (let i = 0; i < a.length; i++) { |
||||
|
categoryData.push(a[i].splice(0, 1)[0]) |
||||
|
values.push(a[i]) |
||||
|
} |
||||
|
return { |
||||
|
categoryData, |
||||
|
values |
||||
|
} |
||||
|
} |
||||
|
var bodongliang = splitData(extractedDrawData.WAVEVOL) |
||||
|
function bodongliangData(values, i) { |
||||
|
return values.map((subArray) => subArray[i]) |
||||
|
} |
||||
|
function calculateMA(index, data) { |
||||
|
let result = [] |
||||
|
if (data.FTLINE) { |
||||
|
data.FTLINE.forEach((item) => { |
||||
|
result.push(item[index]) |
||||
|
}) |
||||
|
} |
||||
|
return result |
||||
|
} |
||||
|
function vwToPx(vw) { |
||||
|
return (screenWidth.value * vw) / 100 |
||||
|
} |
||||
|
var dealData = splitData(extractedDrawData.KLine20) |
||||
|
var dealGnBullData = AIGoldBull.value.JN |
||||
|
const textEcharts = t.value |
||||
|
const firstLegend = computed(() => { |
||||
|
if (screenWidth.value < 768) { |
||||
|
if (textEcharts.suoxie === 'en' || textEcharts.suoxie === 'th') { |
||||
|
return '2%' |
||||
|
} else if (textEcharts.suoxie === 'kr') { |
||||
|
return '2%' |
||||
|
} else { |
||||
|
return '2%' |
||||
|
} |
||||
|
} else { |
||||
|
return textEcharts.suoxie === 'en' || |
||||
|
textEcharts.suoxie === 'th' || |
||||
|
textEcharts.suoxie === 'kr' |
||||
|
? '9%' |
||||
|
: '9%' |
||||
|
} |
||||
|
}) |
||||
|
const processBarData = (data) => { |
||||
|
const barData = [] |
||||
|
data.forEach((item) => { |
||||
|
let color |
||||
|
switch (item[4]) { |
||||
|
case 1: |
||||
|
color = '#13E113' |
||||
|
break |
||||
|
case 2: |
||||
|
color = '#FF0E00' |
||||
|
break |
||||
|
case 3: |
||||
|
color = '#0000FE' |
||||
|
break |
||||
|
case 4: |
||||
|
color = '#1397FF' |
||||
|
break |
||||
|
} |
||||
|
barData.push({ |
||||
|
value: item[5], |
||||
|
itemStyle: { |
||||
|
normal: { |
||||
|
color: color |
||||
|
} |
||||
|
} |
||||
|
}) |
||||
|
}) |
||||
|
return { barData } |
||||
|
} |
||||
|
const { barData } = processBarData(dealGnBullData) |
||||
|
option = { |
||||
|
tooltip: { |
||||
|
trigger: 'axis', |
||||
|
axisPointer: { |
||||
|
type: 'cross' |
||||
|
}, |
||||
|
backgroundColor: 'rgba(119, 120, 125, 0.6)', |
||||
|
borderWidth: 1, |
||||
|
borderColor: '#77787D', |
||||
|
padding: 10, |
||||
|
textStyle: { |
||||
|
color: '#fff' |
||||
|
} |
||||
|
}, |
||||
|
axisPointer: { |
||||
|
link: [ |
||||
|
{ |
||||
|
xAxisIndex: 'all' |
||||
|
} |
||||
|
], |
||||
|
label: { |
||||
|
backgroundColor: '#77787D' |
||||
|
} |
||||
|
}, |
||||
|
toolbox: { |
||||
|
show: false |
||||
|
}, |
||||
|
grid: [ |
||||
|
{ |
||||
|
left: screenWidth.value > 768 ? '10%' : '12%', |
||||
|
right: screenWidth.value > 768 ? '4%' : '6%', |
||||
|
top: screenWidth.value > 768 ? '10%' : '12%', |
||||
|
height: screenWidth.value > 768 ? '35%' : '34%', |
||||
|
containLabel: false |
||||
|
}, |
||||
|
{ |
||||
|
left: screenWidth.value > 768 ? '10%' : '12%', |
||||
|
right: screenWidth.value > 768 ? '4%' : '6%', |
||||
|
top: screenWidth.value > 768 ? '48%' : '48%', |
||||
|
height: screenWidth.value > 768 ? '19%' : '21%', |
||||
|
containLabel: false |
||||
|
}, |
||||
|
{ |
||||
|
left: screenWidth.value > 768 ? '10%' : '12%', |
||||
|
right: screenWidth.value > 768 ? '4%' : '6%', |
||||
|
top: screenWidth.value > 768 ? '70%' : '71%', |
||||
|
height: screenWidth.value > 768 ? '19%' : '21%', |
||||
|
containLabel: false |
||||
|
} |
||||
|
], |
||||
|
xAxis: [ |
||||
|
{ |
||||
|
type: 'category', |
||||
|
data: dealData.categoryData, |
||||
|
boundaryGap: true, |
||||
|
axisLine: { onZero: false }, |
||||
|
splitLine: { show: false }, |
||||
|
min: 'dataMin', |
||||
|
max: 'dataMax', |
||||
|
axisPointer: { |
||||
|
z: 100, |
||||
|
label: { |
||||
|
show: false // 不显示标签 |
||||
|
} |
||||
|
}, |
||||
|
axisLine: { |
||||
|
lineStyle: { |
||||
|
color: 'black' |
||||
|
} |
||||
|
}, // |
||||
|
axisLabel: { show: false }, |
||||
|
axisTick: { show: false } |
||||
|
}, |
||||
|
{ |
||||
|
type: 'category', |
||||
|
gridIndex: 1, |
||||
|
data: dealData.categoryData, |
||||
|
boundaryGap: true, |
||||
|
axisPointer: { |
||||
|
z: 100, |
||||
|
label: { |
||||
|
show: false // 不显示标签 |
||||
|
} |
||||
|
}, |
||||
|
axisLine: { lineStyle: { color: 'black' } }, |
||||
|
axisLabel: { |
||||
|
show: false, |
||||
|
interval: 'auto' |
||||
|
}, |
||||
|
axisTick: { show: false } |
||||
|
}, |
||||
|
{ |
||||
|
type: 'category', |
||||
|
gridIndex: 2, |
||||
|
data: dealData.categoryData, |
||||
|
boundaryGap: true, |
||||
|
axisLine: { lineStyle: { color: 'black' } }, |
||||
|
axisLabel: { |
||||
|
show: true, |
||||
|
interval: 'auto', |
||||
|
fontSize: screenWidth.value > 768 ? 15 : 9 |
||||
|
}, |
||||
|
axisTick: { show: false } |
||||
|
} |
||||
|
], |
||||
|
yAxis: [ |
||||
|
{ |
||||
|
scale: true, |
||||
|
gridIndex: 0, |
||||
|
position: 'left', |
||||
|
axisLabel: { |
||||
|
inside: false, |
||||
|
align: 'right', |
||||
|
fontSize: screenWidth.value > 768 ? 15 : 9 |
||||
|
}, |
||||
|
axisLine: { |
||||
|
show: true, |
||||
|
lineStyle: { |
||||
|
fontSize: '', |
||||
|
color: 'black' |
||||
|
} |
||||
|
}, |
||||
|
axisTick: { show: false }, |
||||
|
splitLine: { show: false } |
||||
|
}, |
||||
|
{ |
||||
|
scale: true, |
||||
|
gridIndex: 1, |
||||
|
splitNumber: 4, |
||||
|
min: 0, |
||||
|
minInterval: 1, |
||||
|
axisLabel: { |
||||
|
show: true, |
||||
|
fontSize: screenWidth.value > 768 ? 15 : 9, |
||||
|
margin: 8, |
||||
|
}, |
||||
|
axisLine: { show: true, lineStyle: { color: 'black' } }, |
||||
|
axisTick: { show: false }, |
||||
|
splitLine: { show: true, lineStyle: { type: 'dashed' } }, |
||||
|
boundaryGap: ['20%', '20%'] |
||||
|
}, |
||||
|
{ |
||||
|
scale: true, |
||||
|
gridIndex: 2, |
||||
|
splitNumber: 2, |
||||
|
axisLabel: { |
||||
|
show: true, |
||||
|
fontSize: screenWidth.value > 768 ? 15 : 9 |
||||
|
}, |
||||
|
axisLine: { show: true, lineStyle: { color: 'black' } }, |
||||
|
axisTick: { show: false }, |
||||
|
splitLine: { show: false } |
||||
|
} |
||||
|
], |
||||
|
dataZoom: [ |
||||
|
{ |
||||
|
type: 'inside', |
||||
|
xAxisIndex: [0, 1, 2], |
||||
|
start: 50, |
||||
|
end: 100 |
||||
|
}, |
||||
|
{ |
||||
|
show: true, |
||||
|
xAxisIndex: [0, 1, 2], |
||||
|
type: 'slider', |
||||
|
start: 50, |
||||
|
end: 100 |
||||
|
} |
||||
|
], |
||||
|
series: [ |
||||
|
{ |
||||
|
type: 'candlestick', |
||||
|
name: '日K', |
||||
|
xAxisIndex: 0, |
||||
|
yAxisIndex: 0, |
||||
|
data: dealData.values, |
||||
|
itemStyle: { |
||||
|
normal: { |
||||
|
color0: 'red', |
||||
|
color: 'green', |
||||
|
borderColor0: 'red', |
||||
|
borderColor: 'green' |
||||
|
} |
||||
|
}, |
||||
|
gridIndex: 1 |
||||
|
}, |
||||
|
{ |
||||
|
name: '成交量', |
||||
|
type: 'bar', |
||||
|
barWidth: '70%', |
||||
|
xAxisIndex: 1, |
||||
|
yAxisIndex: 1, |
||||
|
data: barData, |
||||
|
}, |
||||
|
// { |
||||
|
// name: textEcharts.feixian, |
||||
|
// type: 'line', |
||||
|
// data: calculateMA(1, extractedDrawData), |
||||
|
// smooth: true, |
||||
|
// symbol: 'none', |
||||
|
// xAxisIndex: 2, |
||||
|
// yAxisIndex: 2, |
||||
|
// itemStyle: { |
||||
|
// normal: { |
||||
|
// color: '#00a32e', |
||||
|
// lineStyle: { |
||||
|
// color: '#00a32e', |
||||
|
// width: 2, |
||||
|
// type: 'solid' |
||||
|
// } |
||||
|
// } |
||||
|
// } |
||||
|
// }, |
||||
|
// { |
||||
|
// name: textEcharts.zhoongxian, |
||||
|
// type: 'line', |
||||
|
// data: calculateMA(2, extractedDrawData), |
||||
|
// smooth: true, |
||||
|
// symbol: 'none', |
||||
|
// xAxisIndex: 2, |
||||
|
// yAxisIndex: 2, |
||||
|
// itemStyle: { |
||||
|
// normal: { |
||||
|
// color: '#de0000', |
||||
|
// lineStyle: { |
||||
|
// color: '#de0000', |
||||
|
// width: 2, |
||||
|
// type: 'solid' |
||||
|
// } |
||||
|
// } |
||||
|
// } |
||||
|
// }, |
||||
|
// { |
||||
|
// name: textEcharts.tianxian, |
||||
|
// type: 'line', |
||||
|
// data: calculateMA(3, extractedDrawData), |
||||
|
// smooth: true, |
||||
|
// symbol: 'none', |
||||
|
// xAxisIndex: 2, |
||||
|
// yAxisIndex: 2, |
||||
|
// itemStyle: { |
||||
|
// normal: { |
||||
|
// color: '#ffb300', |
||||
|
// lineStyle: { |
||||
|
// color: '#ffb300', |
||||
|
// width: 2, |
||||
|
// type: 'solid' |
||||
|
// } |
||||
|
// } |
||||
|
// } |
||||
|
// }, |
||||
|
// { |
||||
|
// name: textEcharts.liuxian, |
||||
|
// type: 'line', |
||||
|
// data: calculateMA(4, extractedDrawData), |
||||
|
// smooth: true, |
||||
|
// symbol: 'none', |
||||
|
// xAxisIndex: 2, |
||||
|
// yAxisIndex: 2, |
||||
|
// itemStyle: { |
||||
|
// normal: { |
||||
|
// color: '#00c8ff', |
||||
|
// lineStyle: { |
||||
|
// color: '#00c8ff', |
||||
|
// width: 2, |
||||
|
// type: 'solid' |
||||
|
// } |
||||
|
// } |
||||
|
// } |
||||
|
// }, |
||||
|
] |
||||
|
} |
||||
|
initChart() |
||||
|
} |
||||
|
|
||||
|
// 组件挂载时初始化图表 |
||||
|
onMounted(() => { |
||||
|
// 调用图表初始化函数 |
||||
|
fnShowEcharts4(extractedDrawData) |
||||
|
}) |
||||
|
|
||||
|
|
||||
|
// 初始化图表 |
||||
|
const initChart = async () => { |
||||
|
if (!chartRef.value) return |
||||
|
|
||||
|
try { |
||||
|
const chart = await chartRef.value.init(echarts) |
||||
|
chart.setOption(option) |
||||
|
} catch (error) { |
||||
|
console.error('图表初始化失败:', error) |
||||
|
} |
||||
|
} |
||||
|
</script> |
||||
@ -0,0 +1,493 @@ |
|||||
|
<template> |
||||
|
<view class="content"> |
||||
|
<!-- 市场子Tab --> |
||||
|
<view class="sub_tabs"> |
||||
|
<view v-for="(tab, i) in marketTabs" :key="tab" :class="['tab_item', i === activeTabIndex ? 'active' : '']" |
||||
|
@click="switchTab(i)"> |
||||
|
<text>{{ tab }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 大盘指数 --> |
||||
|
<view class="section"> |
||||
|
<view class="section_header"> |
||||
|
<text class="section_title">大盘指数</text> |
||||
|
<text class="section_action" @click="viewMore('indices')">查看更多 ></text> |
||||
|
</view> |
||||
|
<view class="indices_grid"> |
||||
|
<view v-for="(index, i) in countryInfo.mainIndices" :key="i" class="index_item"> |
||||
|
<IndexCard :flagIcon="countryInfo.flag" :indexName="index.name" :currentPrice="index.price" |
||||
|
:changeAmount="index.change" :changePercent="index.changePercent" :isRising="index.isRising" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 今日市场情绪温度 --> |
||||
|
<view class="sentiment"> |
||||
|
<view class="section_subtitle"> |
||||
|
<text>今日市场情绪温度</text> |
||||
|
</view> |
||||
|
<view class="meters"> |
||||
|
<view class="meter_item" v-for="(m, i) in sentimentMeters" :key="i"> |
||||
|
<image class="meter_icon" :class="m.theme" :src="selectIcons[m.theme]" mode="aspectFit"></image> |
||||
|
<view class="meter_info"> |
||||
|
<text class="meter_value" :class="m.theme">{{ m.value }}°C</text> |
||||
|
<text class="meter_label" :class="m.theme">{{ m.label }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 板块 --> |
||||
|
<view class="section"> |
||||
|
<view class="section_header"> |
||||
|
<text class="section_title">板块</text> |
||||
|
<text class="section_action" @click="viewMore('sectors')">查看更多 ></text> |
||||
|
</view> |
||||
|
<view class="sectors_grid"> |
||||
|
<view v-for="(sec, i) in sectors" :key="i" class="sector_item"> |
||||
|
<view class="sector_header"> |
||||
|
<text class="sector_name">{{ sec.name }}</text> |
||||
|
<text :class="['sector_change', sec.isRising ? 'rising' : 'falling']"> |
||||
|
{{ sec.change }} |
||||
|
</text> |
||||
|
</view> |
||||
|
<view class="sector_price">{{ sec.price }}</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 股票 --> |
||||
|
<view class="section"> |
||||
|
<view class="section_header"> |
||||
|
<text class="section_title">股票</text> |
||||
|
<text class="section_action" @click="viewMore('stocks')">查看更多 ></text> |
||||
|
</view> |
||||
|
<view class="table"> |
||||
|
<view class="table_header"> |
||||
|
<text class="cell name">名称</text> |
||||
|
<text class="cell price">最新</text> |
||||
|
<text class="cell change">涨幅</text> |
||||
|
</view> |
||||
|
<view class="table_row" v-for="(stk, i) in stocks" :key="i"> |
||||
|
<view class="cell name"> |
||||
|
<text class="stk_name">{{ stk.name }}</text> |
||||
|
<text class="stk_code">{{ stk.code }}</text> |
||||
|
</view> |
||||
|
<view class="cell price"> |
||||
|
<text class="stk_price">{{ stk.price }}</text> |
||||
|
</view> |
||||
|
<view class="cell change"> |
||||
|
<text :class="['stk_change', stk.isRising ? 'rising' : 'falling']"> |
||||
|
{{ stk.change }} |
||||
|
</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部安全区域 --> |
||||
|
<view class="bottom_safe_area"></view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, computed, onMounted } from 'vue' |
||||
|
import IndexCard from '../../components/IndexCard.vue' |
||||
|
|
||||
|
// 子Tab与操作 |
||||
|
const marketTabs = ['全部', '美股', '纽交所', '纳斯达克'] |
||||
|
const activeTabIndex = ref(0) |
||||
|
const switchTab = (i) => { |
||||
|
activeTabIndex.value = i |
||||
|
} |
||||
|
|
||||
|
// 今日情绪温度示例数据 |
||||
|
const sentimentMeters = [ |
||||
|
{ value: 90, label: '道琼斯', theme: 'hot' }, |
||||
|
{ value: 60, label: '纳斯达克', theme: 'warm' }, |
||||
|
{ value: 20, label: '标普500', theme: 'cool' } |
||||
|
] |
||||
|
|
||||
|
// 图标映射 |
||||
|
const selectIcons = { |
||||
|
hot: '/static/marketSituation-image/hot.png', |
||||
|
warm: '/static/marketSituation-image/warm.png', |
||||
|
cool: '/static/marketSituation-image/cool.png' |
||||
|
} |
||||
|
|
||||
|
// Props |
||||
|
const props = defineProps({ |
||||
|
countryId: { |
||||
|
type: Number, |
||||
|
required: true |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// 国家/地区信息映射 |
||||
|
const countryInfoMap = { |
||||
|
2: { // 新加坡 |
||||
|
name: '新加坡', |
||||
|
flag: '🇸🇬', |
||||
|
isMarketOpen: true, |
||||
|
mainIndices: [ |
||||
|
{ name: '海峡时报指数', price: '3,234.56', change: '+12.34', changePercent: '+0.38%', isRising: true }, |
||||
|
{ name: 'FTSE ST Mid Cap', price: '1,234.56', change: '-5.67', changePercent: '-0.46%', isRising: false } |
||||
|
], |
||||
|
hotStocks: [ |
||||
|
{ name: '星展银行', code: 'D05.SI', price: '35.20', change: '+0.15', isRising: true }, |
||||
|
{ name: '华侨银行', code: 'O39.SI', price: '13.45', change: '-0.05', isRising: false } |
||||
|
] |
||||
|
}, |
||||
|
3: { // 马来西亚 |
||||
|
name: '马来西亚', |
||||
|
flag: '🇲🇾', |
||||
|
isMarketOpen: false, |
||||
|
mainIndices: [ |
||||
|
{ name: '富时大马KLCI指数', price: '1,567.89', change: '+8.90', changePercent: '+0.57%', isRising: true } |
||||
|
], |
||||
|
hotStocks: [ |
||||
|
{ name: '马来亚银行', code: '1155.KL', price: '9.85', change: '+0.10', isRising: true }, |
||||
|
{ name: '大众银行', code: '1295.KL', price: '4.32', change: '-0.02', isRising: false } |
||||
|
] |
||||
|
}, |
||||
|
4: { // 印度尼西亚 |
||||
|
name: '印度尼西亚', |
||||
|
flag: '🇮🇩', |
||||
|
isMarketOpen: true, |
||||
|
mainIndices: [ |
||||
|
{ name: '雅加达综合指数', price: '7,234.56', change: '+45.67', changePercent: '+0.63%', isRising: true } |
||||
|
], |
||||
|
hotStocks: [] |
||||
|
}, |
||||
|
5: { // 美国 |
||||
|
name: '美国', |
||||
|
flag: '🇺🇸', |
||||
|
isMarketOpen: false, |
||||
|
mainIndices: [ |
||||
|
{ name: '道琼斯', price: '45,757.90', change: '-125.22', changePercent: '-0.27%', isRising: false }, |
||||
|
{ name: '纳斯达克', price: '22,333.96', change: '+125.22', changePercent: '+0.47%', isRising: true }, |
||||
|
{ name: '标普500', price: '6,606.08', change: '+125.22', changePercent: '+0.27%', isRising: true } |
||||
|
], |
||||
|
hotStocks: [ |
||||
|
{ name: '苹果', code: 'AAPL', price: '195.89', change: '+2.34', isRising: true }, |
||||
|
{ name: '微软', code: 'MSFT', price: '378.85', change: '-1.23', isRising: false } |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// 计算当前国家信息 |
||||
|
const countryInfo = computed(() => { |
||||
|
return countryInfoMap[props.countryId] || { |
||||
|
name: '未知地区', |
||||
|
flag: '🌍', |
||||
|
isMarketOpen: false, |
||||
|
mainIndices: [], |
||||
|
hotStocks: [] |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// 计算当前国家的板块与股票 |
||||
|
const sectors = computed(() => { |
||||
|
return countryInfoMap[props.countryId]?.sectors || [] |
||||
|
}) |
||||
|
const stocks = computed(() => { |
||||
|
return countryInfoMap[props.countryId]?.stocks || [] |
||||
|
}) |
||||
|
|
||||
|
// 查看更多占位 |
||||
|
const viewMore = (type) => { |
||||
|
// 可根据 type 跳转到相应页面或加载更多 |
||||
|
// 例如:indices/sectors/stocks |
||||
|
// uni.navigateTo({ url: `/pages/marketSituation/${type}List` }) |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.content { |
||||
|
padding: 0 20rpx 20rpx 20rpx; |
||||
|
} |
||||
|
|
||||
|
/* 子Tab */ |
||||
|
.sub_tabs { |
||||
|
display: flex; |
||||
|
gap: 16rpx; |
||||
|
padding: 0 20rpx 20rpx 20rpx; |
||||
|
} |
||||
|
|
||||
|
.tab_item { |
||||
|
padding: 6rpx 20rpx; |
||||
|
border-radius: 5rpx; |
||||
|
background: #f5f5f5; |
||||
|
color: #666; |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.tab_item.active { |
||||
|
background: #ff4444; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.section { |
||||
|
padding: 20rpx; |
||||
|
border-radius: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.section_header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.section_title { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.section_action { |
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.indices_grid { |
||||
|
padding: 20rpx; |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(3, 1fr); |
||||
|
gap: 20rpx; |
||||
|
background-color: #F6F6F6; |
||||
|
} |
||||
|
|
||||
|
/* 情绪温度 */ |
||||
|
.sentiment { |
||||
|
background-color: #F6F6F6; |
||||
|
padding: 0 20rpx 20rpx 20rpx; |
||||
|
} |
||||
|
|
||||
|
.section_subtitle { |
||||
|
font-size: 24rpx; |
||||
|
color: #000000; |
||||
|
padding: 20rpx 0; |
||||
|
} |
||||
|
|
||||
|
.meters { |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(3, 1fr); |
||||
|
gap: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.meter_item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
/* padding: 10rpx; */ |
||||
|
background: #ffffff; |
||||
|
border-radius: 12rpx; |
||||
|
} |
||||
|
|
||||
|
.meter_item image { |
||||
|
width: 100rpx; |
||||
|
height: 100rpx; |
||||
|
} |
||||
|
|
||||
|
.meter_info { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.meter_value { |
||||
|
font-size: 36rpx; |
||||
|
} |
||||
|
|
||||
|
.meter_value.hot { |
||||
|
color: #ff6b6b; |
||||
|
} |
||||
|
|
||||
|
.meter_value.warm { |
||||
|
color: #ffd166; |
||||
|
} |
||||
|
|
||||
|
.meter_value.cool { |
||||
|
color: #60a5fa; |
||||
|
} |
||||
|
|
||||
|
.meter_label { |
||||
|
font-size: 22rpx; |
||||
|
} |
||||
|
|
||||
|
.meter_label.hot { |
||||
|
color: #ff6b6b; |
||||
|
} |
||||
|
|
||||
|
.meter_label.warm { |
||||
|
color: #ffd166; |
||||
|
} |
||||
|
|
||||
|
.meter_label.cool { |
||||
|
color: #60a5fa; |
||||
|
} |
||||
|
|
||||
|
/* 板块 */ |
||||
|
.sectors_grid { |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(3, 1fr); |
||||
|
gap: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.sector_item { |
||||
|
background: #fafafa; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.sector_header { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
margin-bottom: 12rpx; |
||||
|
} |
||||
|
|
||||
|
.sector_name { |
||||
|
font-size: 24rpx; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.sector_change { |
||||
|
font-size: 22rpx; |
||||
|
} |
||||
|
|
||||
|
.sector_change.rising { |
||||
|
color: #e74c3c; |
||||
|
} |
||||
|
|
||||
|
.sector_change.falling { |
||||
|
color: #27ae60; |
||||
|
} |
||||
|
|
||||
|
.sector_price { |
||||
|
font-size: 24rpx; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
/* 股票表 */ |
||||
|
.table { |
||||
|
background: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.table_header, |
||||
|
.table_row { |
||||
|
display: grid; |
||||
|
grid-template-columns: 2fr 1fr 1fr; |
||||
|
padding: 18rpx 20rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.table_header { |
||||
|
background: #fafafa; |
||||
|
} |
||||
|
|
||||
|
.cell.name { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.stk_name { |
||||
|
font-size: 26rpx; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.stk_code { |
||||
|
font-size: 22rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.stk_price { |
||||
|
font-size: 26rpx; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.stk_change { |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.stk_change.rising { |
||||
|
color: #e74c3c; |
||||
|
} |
||||
|
|
||||
|
.stk_change.falling { |
||||
|
color: #27ae60; |
||||
|
} |
||||
|
|
||||
|
.index_item { |
||||
|
background: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.hot_stocks { |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.stocks_list { |
||||
|
background: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.stock_item { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 24rpx 20rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.stock_item:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.stock_info { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.stock_name { |
||||
|
font-size: 28rpx; |
||||
|
color: #333; |
||||
|
display: block; |
||||
|
margin-bottom: 8rpx; |
||||
|
} |
||||
|
|
||||
|
.stock_code { |
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.stock_price { |
||||
|
text-align: right; |
||||
|
} |
||||
|
|
||||
|
.price { |
||||
|
font-size: 28rpx; |
||||
|
color: #333; |
||||
|
display: block; |
||||
|
margin-bottom: 8rpx; |
||||
|
} |
||||
|
|
||||
|
.change { |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.change.rising { |
||||
|
color: #e74c3c; |
||||
|
} |
||||
|
|
||||
|
.change.falling { |
||||
|
color: #27ae60; |
||||
|
} |
||||
|
|
||||
|
.bottom_safe_area { |
||||
|
height: 120rpx; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,301 @@ |
|||||
|
<template> |
||||
|
<view class="content"> |
||||
|
<view class="section" v-if="type === 'forex'"> |
||||
|
<view class="section_title"> |
||||
|
<text class="title_icon">💱</text> |
||||
|
<text>外汇市场</text> |
||||
|
</view> |
||||
|
<view class="forex_grid"> |
||||
|
<view v-for="(item, index) in forexData" :key="index" class="forex_item"> |
||||
|
<view class="forex_pair"> |
||||
|
<text class="base_currency">{{ item.base }}</text> |
||||
|
<text class="separator">/</text> |
||||
|
<text class="quote_currency">{{ item.quote }}</text> |
||||
|
</view> |
||||
|
<view class="forex_price"> |
||||
|
<text class="price">{{ item.price }}</text> |
||||
|
<text :class="['change', item.isRising ? 'rising' : 'falling']"> |
||||
|
{{ item.change }} |
||||
|
</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="section" v-if="type === 'metals'"> |
||||
|
<view class="section_title"> |
||||
|
<text class="title_icon">🥇</text> |
||||
|
<text>贵金属</text> |
||||
|
</view> |
||||
|
<view class="metals_grid"> |
||||
|
<view v-for="(item, index) in metalsData" :key="index" class="metal_item"> |
||||
|
<view class="metal_info"> |
||||
|
<text class="metal_icon">{{ item.icon }}</text> |
||||
|
<text class="metal_name">{{ item.name }}</text> |
||||
|
</view> |
||||
|
<view class="metal_price"> |
||||
|
<text class="price">{{ item.price }}</text> |
||||
|
<text class="unit">{{ item.unit }}</text> |
||||
|
<text :class="['change', item.isRising ? 'rising' : 'falling']"> |
||||
|
{{ item.change }} |
||||
|
</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 市场动态 --> |
||||
|
<view class="market_news"> |
||||
|
<view class="section_title"> |
||||
|
<text class="title_icon">📰</text> |
||||
|
<text>市场动态</text> |
||||
|
</view> |
||||
|
<view class="news_list"> |
||||
|
<view v-for="(news, index) in newsData" :key="index" class="news_item"> |
||||
|
<view class="news_content"> |
||||
|
<text class="news_title">{{ news.title }}</text> |
||||
|
<text class="news_time">{{ news.time }}</text> |
||||
|
</view> |
||||
|
<view class="news_impact" :class="news.impact"> |
||||
|
<text>{{ news.impactText }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 底部安全区域 --> |
||||
|
<view class="bottom_safe_area"></view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, computed } from 'vue' |
||||
|
|
||||
|
// Props |
||||
|
const props = defineProps({ |
||||
|
countryId: { |
||||
|
type: Number, |
||||
|
required: true |
||||
|
} |
||||
|
}) |
||||
|
|
||||
|
// 判断类型 |
||||
|
const type = computed(() => { |
||||
|
return props.countryId === 11 ? 'forex' : 'metals' |
||||
|
}) |
||||
|
|
||||
|
// 外汇数据 |
||||
|
const forexData = ref([ |
||||
|
{ base: 'USD', quote: 'CNY', price: '7.2456', change: '+0.0123', isRising: true }, |
||||
|
{ base: 'EUR', quote: 'USD', price: '1.0876', change: '-0.0034', isRising: false }, |
||||
|
{ base: 'GBP', quote: 'USD', price: '1.2654', change: '+0.0087', isRising: true }, |
||||
|
{ base: 'USD', quote: 'JPY', price: '149.87', change: '+0.45', isRising: true }, |
||||
|
{ base: 'AUD', quote: 'USD', price: '0.6543', change: '-0.0021', isRising: false }, |
||||
|
{ base: 'USD', quote: 'SGD', price: '1.3456', change: '+0.0012', isRising: true } |
||||
|
]) |
||||
|
|
||||
|
// 贵金属数据 |
||||
|
const metalsData = ref([ |
||||
|
{ icon: '🥇', name: '黄金', price: '2,034.56', unit: 'USD/盎司', change: '+12.34', isRising: true }, |
||||
|
{ icon: '🥈', name: '白银', price: '24.87', unit: 'USD/盎司', change: '-0.23', isRising: false }, |
||||
|
{ icon: '⚪', name: '铂金', price: '987.65', unit: 'USD/盎司', change: '+5.67', isRising: true }, |
||||
|
{ icon: '⚫', name: '钯金', price: '1,234.56', unit: 'USD/盎司', change: '-8.90', isRising: false } |
||||
|
]) |
||||
|
|
||||
|
// 新闻数据 |
||||
|
const newsData = ref([ |
||||
|
{ |
||||
|
title: '美联储暗示可能暂停加息', |
||||
|
time: '2小时前', |
||||
|
impact: 'high', |
||||
|
impactText: '高影响' |
||||
|
}, |
||||
|
{ |
||||
|
title: '欧洲央行维持利率不变', |
||||
|
time: '4小时前', |
||||
|
impact: 'medium', |
||||
|
impactText: '中影响' |
||||
|
}, |
||||
|
{ |
||||
|
title: '黄金价格创新高', |
||||
|
time: '6小时前', |
||||
|
impact: 'medium', |
||||
|
impactText: '中影响' |
||||
|
}, |
||||
|
{ |
||||
|
title: '美元指数小幅下跌', |
||||
|
time: '8小时前', |
||||
|
impact: 'low', |
||||
|
impactText: '低影响' |
||||
|
} |
||||
|
]) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.content { |
||||
|
padding: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.section { |
||||
|
margin-bottom: 40rpx; |
||||
|
} |
||||
|
|
||||
|
.section_title { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
font-size: 28rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.title_icon { |
||||
|
font-size: 32rpx; |
||||
|
margin-right: 12rpx; |
||||
|
} |
||||
|
|
||||
|
.forex_grid, .metals_grid { |
||||
|
background: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.forex_item, .metal_item { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 24rpx 20rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.forex_item:last-child, .metal_item:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.forex_pair { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.base_currency { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.separator { |
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
|
margin: 0 8rpx; |
||||
|
} |
||||
|
|
||||
|
.quote_currency { |
||||
|
font-size: 28rpx; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
.forex_price, .metal_price { |
||||
|
text-align: right; |
||||
|
} |
||||
|
|
||||
|
.price { |
||||
|
font-size: 28rpx; |
||||
|
color: #333; |
||||
|
display: block; |
||||
|
margin-bottom: 8rpx; |
||||
|
} |
||||
|
|
||||
|
.unit { |
||||
|
font-size: 20rpx; |
||||
|
color: #999; |
||||
|
margin-left: 8rpx; |
||||
|
} |
||||
|
|
||||
|
.change { |
||||
|
font-size: 24rpx; |
||||
|
} |
||||
|
|
||||
|
.change.rising { |
||||
|
color: #e74c3c; |
||||
|
} |
||||
|
|
||||
|
.change.falling { |
||||
|
color: #27ae60; |
||||
|
} |
||||
|
|
||||
|
.metal_info { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.metal_icon { |
||||
|
font-size: 32rpx; |
||||
|
margin-right: 16rpx; |
||||
|
} |
||||
|
|
||||
|
.metal_name { |
||||
|
font-size: 28rpx; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.market_news { |
||||
|
margin-bottom: 30rpx; |
||||
|
} |
||||
|
|
||||
|
.news_list { |
||||
|
background: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.news_item { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
align-items: center; |
||||
|
padding: 24rpx 20rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.news_item:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.news_content { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.news_title { |
||||
|
font-size: 28rpx; |
||||
|
color: #333; |
||||
|
display: block; |
||||
|
margin-bottom: 8rpx; |
||||
|
} |
||||
|
|
||||
|
.news_time { |
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.news_impact { |
||||
|
padding: 6rpx 12rpx; |
||||
|
border-radius: 16rpx; |
||||
|
font-size: 20rpx; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.news_impact.high { |
||||
|
background: #e74c3c; |
||||
|
} |
||||
|
|
||||
|
.news_impact.medium { |
||||
|
background: #f39c12; |
||||
|
} |
||||
|
|
||||
|
.news_impact.low { |
||||
|
background: #95a5a6; |
||||
|
} |
||||
|
|
||||
|
.bottom_safe_area { |
||||
|
height: 120rpx; |
||||
|
} |
||||
|
</style> |
||||
2258
pages/marketSituation/marketCondition.vue
File diff suppressed because it is too large
View File
@ -0,0 +1,757 @@ |
|||||
|
<!-- @format --> |
||||
|
|
||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<!-- 可滚动内容区域 --> |
||||
|
<scroll-view class="content_scroll" scroll-y="true" :style="{ top: contentTopPosition + 'px' }"> |
||||
|
<view class="content"> |
||||
|
<button @click="goToChartExample">图表</button> |
||||
|
<view class="map"> |
||||
|
<image src="/static/marketSituation-image/map.png" mode="widthFix"></image> |
||||
|
</view> |
||||
|
<view class="global_index"> |
||||
|
<view class="global_index_title"> |
||||
|
{{ $t("marketSituation.globalIndex") }} |
||||
|
</view> |
||||
|
<view class="global_index_more" @click="goToGlobalIndex"> |
||||
|
<text>{{ $t("marketSituation.globalIndexMore") }}</text> |
||||
|
<image src="/static/marketSituation-image/more.png" mode="aspectFit"></image> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<!-- 卡片网格 --> |
||||
|
<view class="cards_grid"> |
||||
|
<view v-for="(card, index) in cardData" :key="index" class="card_item"> |
||||
|
<IndexCard :flagIcon="card.flagIcon" :stockName="card.stockName" :currentPrice="card.currentPrice" :changeAmount="card.changeAmount" :changePercent="card.changePercent" :isRising="card.isRising" @click="viewIndexDetail(card)" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="warn"> |
||||
|
<image src="/static/marketSituation-image/warn.png" mode="aspectFit"></image> |
||||
|
<view class="warn_text_container"> |
||||
|
<text :class="warnTextClass">{{ $t("marketSituation.warn") }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
<!-- 底部安全区域,防止被导航栏遮挡 --> |
||||
|
<view class="bottom_safe_area"></view> |
||||
|
</view> |
||||
|
</scroll-view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { ref, onMounted, watch, nextTick, computed } from "vue"; |
||||
|
import util from "../../common/util.js"; |
||||
|
import IndexCard from "../../components/IndexCard.vue"; |
||||
|
|
||||
|
const iSMT = ref(0); |
||||
|
const searchValue = ref(""); |
||||
|
const contentHeight = ref(0); |
||||
|
const headerHeight = ref(0); // 动态计算的header高度 |
||||
|
const isWarnTextOverflow = ref(false); // warn文字是否溢出 |
||||
|
|
||||
|
const pageIndex = ref(0); |
||||
|
const scrollToView = ref(""); |
||||
|
|
||||
|
// 跳转图表示例页面 |
||||
|
const goToChartExample = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: "/pages/marketSituation/chartExample", |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 计算属性:精准计算content区域的top值 |
||||
|
const contentTopPosition = computed(() => { |
||||
|
const statusBarHeight = iSMT.value || 0; |
||||
|
const currentHeaderHeight = headerHeight.value > 0 ? headerHeight.value : 140; |
||||
|
return statusBarHeight + currentHeaderHeight; |
||||
|
}); |
||||
|
|
||||
|
// warn文字的class计算属性 |
||||
|
const warnTextClass = computed(() => { |
||||
|
return isWarnTextOverflow.value ? "warn_text scroll-active" : "warn_text"; |
||||
|
}); |
||||
|
|
||||
|
// 弹窗相关数据 |
||||
|
const showCountryModal = ref(false); |
||||
|
const selectedCountry = ref("概况"); |
||||
|
const countryList = ref(["概况", "新加坡", "马来西亚", "印度尼西亚", "美国", "中国香港", "泰国", "中国", "加拿大", "越南", "外汇", "贵金属"]); |
||||
|
|
||||
|
// 卡片数据 |
||||
|
const cardData = ref([ |
||||
|
{ |
||||
|
flagIcon: "🇺🇸", |
||||
|
stockName: "道琼斯", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "45757.90", |
||||
|
changeAmount: "-125.22", |
||||
|
changePercent: "-0.27%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "🇺🇸", |
||||
|
stockName: "纳斯达克", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "22333.96", |
||||
|
changeAmount: "+125.22", |
||||
|
changePercent: "+0.47%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "🇺🇸", |
||||
|
stockName: "标普500", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "6606.08", |
||||
|
changeAmount: "+125.22", |
||||
|
changePercent: "+0.27%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "🇨🇳", |
||||
|
stockName: "上证指数", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "3333.96", |
||||
|
changeAmount: "+125.22", |
||||
|
changePercent: "+0.27%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "🇨🇳", |
||||
|
stockName: "科创50", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "757.90", |
||||
|
changeAmount: "-25.22", |
||||
|
changePercent: "-0.27%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "🇭🇰", |
||||
|
stockName: "恒生指数", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "19757.90", |
||||
|
changeAmount: "-125.22", |
||||
|
changePercent: "-0.63%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "🇸🇬", |
||||
|
stockName: "道琼斯", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "3757.90", |
||||
|
changeAmount: "+85.22", |
||||
|
changePercent: "+2.31%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "🇲🇾", |
||||
|
stockName: "纳斯达克", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "1657.90", |
||||
|
changeAmount: "-15.22", |
||||
|
changePercent: "-0.91%", |
||||
|
isRising: false, |
||||
|
}, |
||||
|
{ |
||||
|
flagIcon: "🇹🇭", |
||||
|
stockName: "标普500", |
||||
|
stockCode: "noCode", |
||||
|
currentPrice: "1457.90", |
||||
|
changeAmount: "+35.22", |
||||
|
changePercent: "+2.48%", |
||||
|
isRising: true, |
||||
|
}, |
||||
|
]); |
||||
|
|
||||
|
// 搜索输入事件 |
||||
|
const onSearchInput = (e) => { |
||||
|
searchValue.value = e.detail.value; |
||||
|
}; |
||||
|
|
||||
|
// 搜索确认事件 |
||||
|
const onSearchConfirm = (e) => { |
||||
|
console.log("搜索内容:", e.detail.value); |
||||
|
// 这里可以添加搜索逻辑 |
||||
|
performSearch(e.detail.value); |
||||
|
}; |
||||
|
|
||||
|
// 搜索图标点击事件 |
||||
|
const onSearchClick = () => { |
||||
|
if (searchValue.value.trim()) { |
||||
|
performSearch(searchValue.value); |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
// 执行搜索 |
||||
|
const performSearch = (keyword) => { |
||||
|
if (!keyword.trim()) { |
||||
|
uni.showToast({ |
||||
|
title: "请输入搜索内容", |
||||
|
icon: "none", |
||||
|
}); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
uni.showToast({ |
||||
|
title: `搜索: ${keyword}`, |
||||
|
icon: "none", |
||||
|
}); |
||||
|
// 这里添加实际的搜索逻辑 |
||||
|
}; |
||||
|
|
||||
|
// 检测warn文字是否溢出 |
||||
|
const checkWarnTextOverflow = () => { |
||||
|
nextTick(() => { |
||||
|
setTimeout(() => { |
||||
|
const query = uni.createSelectorQuery(); |
||||
|
|
||||
|
// 同时查询容器和文字元素 |
||||
|
query.select(".warn_text_container").boundingClientRect(); |
||||
|
query.select(".warn_text").boundingClientRect(); |
||||
|
query.exec((res) => { |
||||
|
const containerRect = res[0]; |
||||
|
const textRect = res[1]; |
||||
|
|
||||
|
if (!containerRect || !textRect) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// 判断文字是否超出容器(留一些余量) |
||||
|
const isOverflow = textRect.width > containerRect.width - 10; |
||||
|
|
||||
|
isWarnTextOverflow.value = isOverflow; |
||||
|
}); |
||||
|
}, 500); |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 方法:查看指数详情 |
||||
|
const viewIndexDetail = (item) => { |
||||
|
console.log("查看指数详情:", item.stockName); |
||||
|
// uni.showToast({ |
||||
|
// title: `查看 ${item.stockName} 详情`, |
||||
|
// icon: 'none', |
||||
|
// duration: 2000 |
||||
|
// }) |
||||
|
// 这里可以跳转到具体的指数详情页面 |
||||
|
uni.navigateTo({ |
||||
|
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}`, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
// 跳转到全球指数页面 |
||||
|
const goToGlobalIndex = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: "/pages/marketSituation/globalIndex", |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
|
||||
|
// 确保DOM渲染完成后再查询高度 |
||||
|
nextTick(() => { |
||||
|
// 动态计算header实际高度 |
||||
|
uni |
||||
|
.createSelectorQuery() |
||||
|
.select(".header_fixed") |
||||
|
.boundingClientRect((rect) => { |
||||
|
if (rect) { |
||||
|
headerHeight.value = rect.height; |
||||
|
console.log("Header实际高度:", headerHeight.value, "px"); |
||||
|
} |
||||
|
}) |
||||
|
.exec(); |
||||
|
|
||||
|
// 检测warn文字是否溢出 |
||||
|
checkWarnTextOverflow(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
// 监听headerHeight变化,重新计算contentHeight |
||||
|
watch(headerHeight, (newHeight) => { |
||||
|
if (newHeight > 0) { |
||||
|
const systemInfo = uni.getSystemInfoSync(); |
||||
|
const windowHeight = systemInfo.windowHeight; |
||||
|
const statusBarHeight = systemInfo.statusBarHeight || 0; |
||||
|
const footerHeight = 100; |
||||
|
|
||||
|
contentHeight.value = windowHeight - statusBarHeight - newHeight - footerHeight; |
||||
|
console.log("重新计算contentHeight:", contentHeight.value); |
||||
|
} |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
/* 状态栏占位 */ |
||||
|
.top { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
z-index: 1001; |
||||
|
background-color: #ffffff; |
||||
|
} |
||||
|
|
||||
|
/* 固定头部样式 */ |
||||
|
.header_fixed { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
z-index: 1000; |
||||
|
background-color: #ffffff; |
||||
|
padding: 20rpx 0 0 0; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
/* 可滚动内容区域 */ |
||||
|
.content_scroll { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 100rpx; |
||||
|
/* 底部导航栏高度 */ |
||||
|
overflow-y: auto; |
||||
|
} |
||||
|
|
||||
|
.header_content { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: space-between; |
||||
|
height: 80rpx; |
||||
|
padding: 0 20rpx; |
||||
|
margin-bottom: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.header_input_wrapper { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
width: 100%; |
||||
|
margin: 0 20rpx 0 0; |
||||
|
height: 70rpx; |
||||
|
border-radius: 35rpx; |
||||
|
background-color: #ffffff; |
||||
|
border: 1rpx solid #e9ecef; |
||||
|
padding: 0 80rpx 0 30rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #5c5c5c; |
||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
.search_icon { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
opacity: 0.6; |
||||
|
} |
||||
|
|
||||
|
.header_input { |
||||
|
margin-left: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.header_icons { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
gap: 15rpx; |
||||
|
} |
||||
|
|
||||
|
.header_icon { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.header_icon image { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
} |
||||
|
|
||||
|
/* Tab 栏样式 */ |
||||
|
.channel_li { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 80rpx; |
||||
|
background-color: #ffffff; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.channel_wrap { |
||||
|
width: calc(100% - 60rpx); |
||||
|
height: 100%; |
||||
|
overflow: hidden; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.channel_innerWrap { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 100%; |
||||
|
padding: 0 20rpx; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.channel_item { |
||||
|
position: relative; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
height: 60rpx; |
||||
|
padding: 0 20rpx; |
||||
|
border-radius: 30rpx; |
||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
||||
|
cursor: pointer; |
||||
|
white-space: nowrap; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.channel_item:active { |
||||
|
transform: scale(0.98); |
||||
|
} |
||||
|
|
||||
|
.channel_item.active { |
||||
|
color: #333; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.channel_text { |
||||
|
font-size: 28rpx; |
||||
|
font-weight: 500; |
||||
|
color: #666666; |
||||
|
transition: color 0.3s ease; |
||||
|
white-space: nowrap; |
||||
|
} |
||||
|
|
||||
|
.channel_item.active .channel_text { |
||||
|
color: #333333; |
||||
|
font-weight: 400; |
||||
|
z-index: 2; |
||||
|
} |
||||
|
|
||||
|
.active_indicator { |
||||
|
position: absolute; |
||||
|
left: 50%; |
||||
|
top: 60%; |
||||
|
transform: translateX(-45%); |
||||
|
width: calc(100% - 20rpx); |
||||
|
min-width: 40rpx; |
||||
|
max-width: 120rpx; |
||||
|
height: 8rpx; |
||||
|
background-image: url("/static/marketSituation-image/bg.png"); |
||||
|
background-size: cover; |
||||
|
background-position: center; |
||||
|
background-repeat: no-repeat; |
||||
|
animation: slideIn 0.1s ease; |
||||
|
border-radius: 8rpx; |
||||
|
z-index: 1; |
||||
|
} |
||||
|
|
||||
|
@keyframes slideIn { |
||||
|
from { |
||||
|
width: 0; |
||||
|
opacity: 0; |
||||
|
} |
||||
|
|
||||
|
to { |
||||
|
width: 40rpx; |
||||
|
opacity: 1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.scroll_indicator { |
||||
|
border-left: 1rpx solid #b6b6b6; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
width: 60rpx; |
||||
|
height: 30rpx; |
||||
|
background-color: #ffffff; |
||||
|
flex-shrink: 0; |
||||
|
} |
||||
|
|
||||
|
.scroll_indicator image { |
||||
|
width: 20rpx; |
||||
|
height: 20rpx; |
||||
|
opacity: 0.5; |
||||
|
} |
||||
|
|
||||
|
.content { |
||||
|
margin-top: 20rpx; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.map { |
||||
|
width: calc(100% - 60rpx); |
||||
|
margin: 0 30rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
background-color: #f3f3f3; |
||||
|
border-radius: 30rpx; |
||||
|
border: 1rpx solid #e0e0e0; |
||||
|
padding: 30rpx 20rpx; |
||||
|
box-sizing: border-box; |
||||
|
/* 设置最小高度保护,但允许内容撑开 */ |
||||
|
min-height: 200rpx; |
||||
|
} |
||||
|
|
||||
|
.map image { |
||||
|
width: 100%; |
||||
|
height: auto; |
||||
|
max-width: 100%; |
||||
|
display: block; |
||||
|
/* widthFix模式下,高度会自动按比例调整 */ |
||||
|
/* 设置最大高度避免图片过大 */ |
||||
|
max-height: 60vh; |
||||
|
/* 添加平滑过渡效果 */ |
||||
|
transition: all 0.3s ease; |
||||
|
max-height: 60vh; |
||||
|
} |
||||
|
|
||||
|
/* 响应式优化 */ |
||||
|
@media screen and (max-width: 750rpx) { |
||||
|
.map { |
||||
|
margin: 0 20rpx; |
||||
|
width: calc(100% - 40rpx); |
||||
|
padding: 20rpx 15rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@media screen and (max-width: 480rpx) { |
||||
|
.map { |
||||
|
margin: 0 15rpx; |
||||
|
width: calc(100% - 30rpx); |
||||
|
padding: 15rpx 10rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.static-footer { |
||||
|
position: fixed; |
||||
|
bottom: 0; |
||||
|
} |
||||
|
|
||||
|
/* 弹窗样式 */ |
||||
|
.modal_overlay { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
background-color: rgba(0, 0, 0, 0.5); |
||||
|
display: flex; |
||||
|
align-items: flex-end; |
||||
|
z-index: 1000; |
||||
|
} |
||||
|
|
||||
|
.modal_content { |
||||
|
width: 100%; |
||||
|
background-color: #fff; |
||||
|
border-radius: 20rpx 20rpx 0 0; |
||||
|
max-height: 80vh; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.modal_header { |
||||
|
position: relative; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
padding: 30rpx 40rpx; |
||||
|
border-bottom: 1rpx solid #f0f0f0; |
||||
|
} |
||||
|
|
||||
|
.modal_title { |
||||
|
font-size: 32rpx; |
||||
|
font-weight: bold; |
||||
|
color: #333333; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.modal_close { |
||||
|
position: absolute; |
||||
|
right: 40rpx; |
||||
|
top: 50%; |
||||
|
transform: translateY(-50%); |
||||
|
width: 60rpx; |
||||
|
height: 60rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
font-size: 40rpx; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.modal_body { |
||||
|
padding: 40rpx; |
||||
|
} |
||||
|
|
||||
|
.country_grid { |
||||
|
display: grid; |
||||
|
grid-template-columns: 1fr 1fr; |
||||
|
gap: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.country_item { |
||||
|
padding: 24rpx 30rpx; |
||||
|
border-radius: 12rpx; |
||||
|
background-color: #f8f8f8; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
transition: all 0.3s ease; |
||||
|
} |
||||
|
|
||||
|
.country_item.selected { |
||||
|
background-color: #ff4444; |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.country_text { |
||||
|
font-size: 28rpx; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.country_item.selected .country_text { |
||||
|
color: #fff; |
||||
|
} |
||||
|
|
||||
|
.global_index { |
||||
|
margin: 30rpx 20rpx 0 20rpx; |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
} |
||||
|
|
||||
|
.global_index_title { |
||||
|
margin-left: 20rpx; |
||||
|
font-size: 40rpx; |
||||
|
font-weight: 100; |
||||
|
color: #333333; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.global_index_more { |
||||
|
display: flex; |
||||
|
gap: 10rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #333333; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.global_index_more image { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
/* 卡片网格样式 */ |
||||
|
.cards_grid { |
||||
|
display: grid; |
||||
|
grid-template-columns: repeat(3, 1fr); |
||||
|
margin: 0; |
||||
|
box-sizing: border-box; |
||||
|
width: 100%; |
||||
|
padding: 30rpx 20rpx; |
||||
|
gap: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.card_item { |
||||
|
width: 100%; |
||||
|
box-sizing: border-box; |
||||
|
min-width: 0; |
||||
|
/* 防止内容溢出 */ |
||||
|
} |
||||
|
|
||||
|
/* 响应式布局 - 小屏幕时改为两列 */ |
||||
|
@media (max-width: 600rpx) { |
||||
|
.cards_grid { |
||||
|
grid-template-columns: repeat(2, 1fr); |
||||
|
padding: 30rpx 20rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 超小屏幕时改为单列 */ |
||||
|
@media (max-width: 400rpx) { |
||||
|
.cards_grid { |
||||
|
grid-template-columns: 1fr; |
||||
|
padding: 30rpx 20rpx; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.warn { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: flex-start; |
||||
|
gap: 10rpx; |
||||
|
font-size: 28rpx; |
||||
|
color: #666666; |
||||
|
padding: 20rpx; |
||||
|
max-width: 100%; |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.warn image { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
flex-shrink: 0; |
||||
|
/* 防止图片被压缩 */ |
||||
|
position: relative; |
||||
|
z-index: 2; |
||||
|
/* 确保图片在最上层 */ |
||||
|
} |
||||
|
|
||||
|
.warn_text_container { |
||||
|
flex: 1; |
||||
|
overflow: hidden; |
||||
|
position: relative; |
||||
|
min-width: 0; |
||||
|
/* 允许容器收缩 */ |
||||
|
} |
||||
|
|
||||
|
.warn_text { |
||||
|
display: block; |
||||
|
white-space: nowrap; |
||||
|
will-change: transform; |
||||
|
/* 优化动画性能 */ |
||||
|
} |
||||
|
|
||||
|
/* 文字滚动动画 */ |
||||
|
@keyframes scrollText { |
||||
|
0% { |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
|
||||
|
20% { |
||||
|
transform: translateX(0); |
||||
|
} |
||||
|
|
||||
|
80% { |
||||
|
transform: translateX(-85%); |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
transform: translateX(-85%); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* 当文字超长时启用滚动动画 */ |
||||
|
.warn_text.scroll-active { |
||||
|
animation: scrollText 12s linear infinite; |
||||
|
animation-delay: 2s; |
||||
|
/* 延迟2秒开始滚动,让用户先看到开头 */ |
||||
|
} |
||||
|
|
||||
|
/* 底部安全区域 */ |
||||
|
.bottom_safe_area { |
||||
|
height: 40rpx; |
||||
|
background-color: transparent; |
||||
|
} |
||||
|
|
||||
|
/* 主容器样式调整 */ |
||||
|
.main { |
||||
|
position: relative; |
||||
|
height: 100vh; |
||||
|
overflow: hidden; |
||||
|
background-color: white; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,86 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view style="height:1.5vh" /> |
||||
|
<view class="top"> |
||||
|
<img src="/static/my/aboutDC.png"></img> |
||||
|
</view> |
||||
|
|
||||
|
<view class="bottom"> |
||||
|
<view class="bottom-list" @click="goToIntroduce"> |
||||
|
<text class="label">产品介绍</text> |
||||
|
<uni-icons type="arrowright" size="16" /> |
||||
|
</view> |
||||
|
<view class="bottom-list"> |
||||
|
<text class="label">免责声明</text> |
||||
|
<uni-icons type="arrowright" size="16" /> |
||||
|
</view> |
||||
|
<view class="bottom-list"> |
||||
|
<text class="label">隐私政策</text> |
||||
|
<uni-icons type="arrowright" size="16" /> |
||||
|
</view> |
||||
|
<view class="bottom-list"> |
||||
|
<text class="label">服务协议</text> |
||||
|
<uni-icons type="arrowright" size="16" /> |
||||
|
</view> |
||||
|
<view class="bottom-list"> |
||||
|
<text class="label">鼓励一下</text> |
||||
|
<uni-icons type="arrowright" size="16" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const goToIntroduce = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url: '../setting/introduce' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
height: 23vh; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 35vh; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.bottom-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin: 0 40rpx; |
||||
|
padding: 0 10rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.bottom-list:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.label{ |
||||
|
flex:1; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,218 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view style="height:1.5vh;"></view> |
||||
|
|
||||
|
<view class="setting-list"> |
||||
|
<view class="setting-item"> |
||||
|
<text class="item-label">头像</text> |
||||
|
<view class="item-right"> |
||||
|
<image src="/static/avatar.png" class="avatar" mode="aspectFill"></image> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow"></uni-icons> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="setting-item"> |
||||
|
<text class="item-label">昵称</text> |
||||
|
<view class="item-right"> |
||||
|
<text class="item-text">DeepChart</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow"></uni-icons> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="setting-item"> |
||||
|
<text class="item-label">ID</text> |
||||
|
<view class="item-right"> |
||||
|
<text class="item-text">{{ jwcode }}</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow"></uni-icons> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="setting-item"> |
||||
|
<text class="item-label">密码</text> |
||||
|
<view class="item-right"> |
||||
|
<text class="item-text">qwertyuiop</text> |
||||
|
<uni-icons type="eye" size="16" class="eye-icon"></uni-icons> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view class="setting-item" @click="goToPassword"> |
||||
|
<text class="item-label">修改密码</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow"></uni-icons> |
||||
|
</view> |
||||
|
<view class="setting-item"> |
||||
|
<text class="item-label">注销账号</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow"></uni-icons> |
||||
|
</view> |
||||
|
<view class="setting-item" @click="goToBind"> |
||||
|
<text class="item-label">绑定账号</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow"></uni-icons> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view style="height:1.5vh;"></view> |
||||
|
|
||||
|
<view class="logout" @click="showLogout = true"> |
||||
|
<text>退出登录</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="logout-confirm" v-if="showLogout"> |
||||
|
<view class="logoutDialog"> |
||||
|
<view class="tips">是否退出登录</view> |
||||
|
<view class="tips-button"> |
||||
|
<button class="confirm-btn" @click="handleConfirmLogout">确认</button> |
||||
|
<button class="cancel-btn" @click="showLogout = false">取消</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
|
||||
|
import {useUserStore} from "../../stores/modules/userInfo" |
||||
|
const iSMT = ref(0) |
||||
|
const jwcode = ref('90047681') |
||||
|
const showLogout = ref(false) |
||||
|
const userStore = useUserStore() |
||||
|
|
||||
|
const handleConfirmLogout = () => { |
||||
|
|
||||
|
userStore.clearUserInfo() |
||||
|
showLogout.value = false |
||||
|
uni.showToast({ |
||||
|
title: '退出登录成功', |
||||
|
icon: 'none', |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToBind = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/bind' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToPassword = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/password' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.setting-list { |
||||
|
height: 49vh; |
||||
|
background-color: #fff; |
||||
|
} |
||||
|
|
||||
|
.setting-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 7vh; |
||||
|
padding: 0 40rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.setting-item:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.item-label { |
||||
|
font-size: 28rpx; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.item-right { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.avatar { |
||||
|
width: 60rpx; |
||||
|
height: 60rpx; |
||||
|
border-radius: 50%; |
||||
|
margin-right: 20rpx; |
||||
|
background-color: #999; |
||||
|
} |
||||
|
|
||||
|
.item-text { |
||||
|
margin-right: 20rpx; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.arrow, |
||||
|
.eye-icon { |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.logout { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
height: 7vh; |
||||
|
font-size: 28rpx; |
||||
|
color: #f56c6c; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.logout-confirm { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
width: 100%; |
||||
|
height: 100%; |
||||
|
background-color: rgba(0, 0, 0, 0.5); |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
z-index: 999; |
||||
|
} |
||||
|
|
||||
|
.logoutDialog { |
||||
|
width: 500rpx; |
||||
|
background-color: #fff; |
||||
|
border-radius: 12rpx; |
||||
|
padding: 40rpx; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.tips { |
||||
|
font-size: 32rpx; |
||||
|
margin-bottom: 40rpx; |
||||
|
} |
||||
|
|
||||
|
.tips-button { |
||||
|
display: flex; |
||||
|
width: 100%; |
||||
|
justify-content: space-between; |
||||
|
} |
||||
|
|
||||
|
.confirm-btn, |
||||
|
.cancel-btn { |
||||
|
width: 180rpx; |
||||
|
height: 60rpx; |
||||
|
line-height: 60rpx; |
||||
|
border-radius: 30rpx; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.confirm-btn { |
||||
|
background-color: #fff; |
||||
|
color: #000; |
||||
|
border: 1rpx solid #ddd; |
||||
|
} |
||||
|
|
||||
|
.cancel-btn { |
||||
|
background-color: #000; |
||||
|
color: #fff; |
||||
|
border: none; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,85 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view style="height:1.5vh;" /> |
||||
|
|
||||
|
<view class="top"> |
||||
|
<view class="top-list" @click="goToBindPhone"> |
||||
|
<text class="label">手机号</text> |
||||
|
<view class="right"> |
||||
|
<text style="font-size: 28rpx;">未绑定</text> |
||||
|
<uni-icons type="arrowright" size="16" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="top-list" @click="goToBindEmail"> |
||||
|
<text class="label">邮箱</text> |
||||
|
<view class="right"> |
||||
|
<text style="font-size: 28rpx;">analsak@163.com</text> |
||||
|
<uni-icons type="arrowright" size="16" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const goToBindPhone = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/phone' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToBindEmail = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/email' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
height: 14vh; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
margin: 0rpx 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.top-list:last-child { |
||||
|
border: none; |
||||
|
} |
||||
|
|
||||
|
.label { |
||||
|
font-size: 28rpx; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.right{ |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,142 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view style="height:1.5vh;" /> |
||||
|
|
||||
|
<view class="top"> |
||||
|
<view class="top-list"> |
||||
|
<view class="left"> |
||||
|
<img src="/static/my/bindedEmail.png" /> |
||||
|
<text class="label">已绑邮箱:{{ email }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="top-list"> |
||||
|
<view class="left"> |
||||
|
<img src="/static/my/changeEmail.png" /> |
||||
|
<text class="label">+86</text> |
||||
|
<input type="number" placeholder="请输入您的换绑邮箱" class="input" /> |
||||
|
</view> |
||||
|
<view class="right"> |
||||
|
<button class="verification" :class="{ 'disabled': gettingCode }" @click="getVerification" |
||||
|
:disabled="gettingCode"> |
||||
|
{{ gettingCode ? `重新发送 ${time}s` : '获取验证码' }} |
||||
|
</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="top-list"> |
||||
|
<view class="left"> |
||||
|
<img src="/static/my/verification.png" /> |
||||
|
<input type="text" placeholder="请输入验证码" class="input" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="bottom"> |
||||
|
<button class="change-btn">换绑</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const email = ref('analsak@16.com') |
||||
|
const gettingCode = ref(false) |
||||
|
const time = ref(60) |
||||
|
|
||||
|
const getVerification = () => { |
||||
|
if (gettingCode.value) return |
||||
|
gettingCode.value = true |
||||
|
|
||||
|
time.value = 60 |
||||
|
const timer = setInterval(() => { |
||||
|
time.value-- |
||||
|
if (time.value <= 0) { |
||||
|
clearInterval(timer) |
||||
|
gettingCode.value = false |
||||
|
} |
||||
|
}, 1000) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
height: auto; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
margin: 0rpx 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.left { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.label { |
||||
|
font-size: 28rpx; |
||||
|
margin-left: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.right { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.input { |
||||
|
flex: 1; |
||||
|
height: 70rpx; |
||||
|
font-size: 29rpx; |
||||
|
margin-left: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.verification { |
||||
|
font-size: 24rpx; |
||||
|
border-radius: 10rpx; |
||||
|
background-color: rgb(230, 230, 230); |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 22vh; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.change-btn { |
||||
|
height: 85rpx; |
||||
|
width: 610rpx; |
||||
|
padding:0 20rpx; |
||||
|
background-color: black; |
||||
|
color: white; |
||||
|
border-radius: 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,68 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
<view class="top"> |
||||
|
<view class="top-list"> |
||||
|
<text>标准</text> |
||||
|
<radio value="0" class="radio-btn" activeBackgroundColor="red" |
||||
|
:checked="selectedIndex === 0" @click="selectFont(0)" /> |
||||
|
</view> |
||||
|
<view class="top-list"> |
||||
|
<text>中号</text> |
||||
|
<radio value="1" class="radio-btn" activeBackgroundColor="red" |
||||
|
:checked="selectedIndex === 1" @click="selectFont(1)" /> |
||||
|
</view> |
||||
|
<view class="top-list"> |
||||
|
<text>大号</text> |
||||
|
<radio value="2" class="radio-btn" activeBackgroundColor="red" |
||||
|
:checked="selectedIndex === 2" @click="selectFont(2)" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const selectedIndex = ref(0) |
||||
|
|
||||
|
const selectFont = (index) => { |
||||
|
selectedIndex.value = index |
||||
|
console.log('看看选中状态',selectedIndex.value) |
||||
|
} |
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
margin-top: 1.5vh; |
||||
|
height: 21vh; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin: 0 40rpx; |
||||
|
padding:0 10rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.top-list:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.radio-btn { |
||||
|
margin-left: auto; |
||||
|
transform: scale(0.6); |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,165 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
<view class="top"> |
||||
|
<view class="top-list"> |
||||
|
<text>语言</text> |
||||
|
<text class="language">中文(简体)</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
<view class="top-list" @click="goToFont"> |
||||
|
<text>字体大小</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
<view class="top-list" @click="goToTheme"> |
||||
|
<text>主题切换</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
|
||||
|
<view class="center"> |
||||
|
<view class="center-list" @click="goToMessage"> |
||||
|
<text>消息推送</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="bottom"> |
||||
|
<view class="bottom-list" @click="goToServer"> |
||||
|
<text>切换服务器</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
<view class="bottom-list" @click="clearCache"> |
||||
|
<text>清理缓存</text> |
||||
|
<text class="cache">{{ cache }}M</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const cache = ref('45.5') |
||||
|
|
||||
|
const goToFont = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/setting/font' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToTheme = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/setting/theme' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToMessage = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/setting/message' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const goToServer = () => { |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/setting/server' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const clearCache = () => { |
||||
|
cache.value = 0 |
||||
|
uni.showToast({ |
||||
|
title: '清理成功', |
||||
|
icon: 'success', |
||||
|
duration: 1500 |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
margin-top: 1.5vh; |
||||
|
height: 21vh; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin: 0 40rpx; |
||||
|
padding: 0 10rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.top-list:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.language { |
||||
|
margin-left: 55%; |
||||
|
font-size: 14px; |
||||
|
color: rgb(203, 203, 203); |
||||
|
} |
||||
|
|
||||
|
.arrow { |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
|
||||
|
.center { |
||||
|
background-color: white; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin-top: 1vh; |
||||
|
} |
||||
|
|
||||
|
.center-list { |
||||
|
width: 630rpx; |
||||
|
margin: 0rpx 40rpx; |
||||
|
display: flex; |
||||
|
padding: 0 10rpx; |
||||
|
} |
||||
|
|
||||
|
.center-list>.arrow { |
||||
|
margin-right: 0; |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 13.5vh; |
||||
|
background-color: white; |
||||
|
margin-top: 1vh; |
||||
|
} |
||||
|
|
||||
|
.bottom-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin: 0 40rpx; |
||||
|
padding: 0 10rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.cache { |
||||
|
margin-left: 55%; |
||||
|
font-size: 14px; |
||||
|
color: rgb(203, 203, 203); |
||||
|
} |
||||
|
|
||||
|
.bottom-list:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,76 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view style="height:1.5vh" /> |
||||
|
<view class="top"> |
||||
|
<img src="/static/my/aboutDC.png"></img> |
||||
|
</view> |
||||
|
|
||||
|
<view class="bottom"> |
||||
|
<view class="title">1.产品定位</view> |
||||
|
<view class="main-text">DeepChart:全球最懂机构行为的AI(你的AI投资伙伴)强化"深度分析" |
||||
|
的品牌标签(DeepChart=全球最懂机构行为的AI),主打"深度解读机构行为"的APP。</view> |
||||
|
|
||||
|
<view class="title">2.产品介绍</view> |
||||
|
<view class="main-text">DeepChart是一款以"Al智能体”为决策核心的智能投资分析平台, |
||||
|
专注于深度研究机构行为,专为全球散户投资者量身打造。它重新定义了人与投资工具之间的关系, |
||||
|
是一个真正懂投资、懂市场、更懂用户的AI投资伙伴。</view> |
||||
|
|
||||
|
<view class="title">3.产品理念</view> |
||||
|
<view class="main-text">从“人找信息”到“AI智能体替你思考和管理”。</view> |
||||
|
|
||||
|
<view class="title">4.功能定位——全景AI决策体系</view> |
||||
|
<view class="main-text">黄其振是大笨蛋</view> |
||||
|
<view class="main-text">李建霖是大笨蛋</view> |
||||
|
<view class="main-text">double是大笨蛋</view> |
||||
|
<view class="main-text">张鲁平是大笨蛋</view> |
||||
|
<view style="height:1.5vh;background-color: white;" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
height: 26vh; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 35vh; |
||||
|
padding: 0 60rpx; |
||||
|
background-color: white; |
||||
|
height: auto; |
||||
|
} |
||||
|
|
||||
|
.title { |
||||
|
font-size: 30rpx; |
||||
|
font-weight: bold; |
||||
|
margin-bottom: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.main-text { |
||||
|
font-size: 27rpx; |
||||
|
margin-bottom: 20rpx; |
||||
|
color: rgb(122, 122, 122); |
||||
|
text-align: justify; |
||||
|
text-justify: inter-character;/* 两端对齐哈哈哈哈 */ |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,221 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view class="time-share-title"> |
||||
|
<text>分时设计</text> |
||||
|
</view> |
||||
|
<view style="height:57.5vh;background-color: white;"> |
||||
|
<view class="title">A股竞价</view> |
||||
|
<view class="top-options"> |
||||
|
<view class="option-btn" :class="{ 'active': aStockBid === 0 }" @click="aStockBid = 0"> |
||||
|
<text>智能开启</text> |
||||
|
<view class="active-dot" v-if="aStockBid === 0"></view> |
||||
|
</view> |
||||
|
<view class="option-btn" :class="{ 'active': aStockBid === 1 }" @click="aStockBid = 1"> |
||||
|
<text>保持开启</text> |
||||
|
<view class="active-dot" v-if="aStockBid === 1"></view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="option-btn" :class="{ 'active': aStockBid === 2 }" @click="aStockBid = 2"> |
||||
|
<text>保持关闭</text> |
||||
|
<view class="active-dot" v-if="aStockBid === 2"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="title">K线样式</view> |
||||
|
<view class="top-options"> |
||||
|
<view class="option-btn" :class="{ 'active': kStyle === 0 }" @click="kStyle = 0"> |
||||
|
<img src="/static/my/common.png" class="kline-icon" /> |
||||
|
<text>普通</text> |
||||
|
<view class="active-dot" v-if="kStyle === 0"></view> |
||||
|
</view> |
||||
|
<view class="option-btn" :class="{ 'active': kStyle === 1 }" @click="kStyle = 1"> |
||||
|
<img src="/static/my/outline.png" class="kline-icon" /> |
||||
|
<text>轮廓图</text> |
||||
|
<view class="active-dot" v-if="kStyle === 1"></view> |
||||
|
</view> |
||||
|
<view class="option-btn" :class="{ 'active': kStyle === 2 }" @click="kStyle = 2"> |
||||
|
<img src="/static/my/polylines.png" class="kline-icon" /> |
||||
|
<text>折线图</text> |
||||
|
<view class="active-dot" v-if="kStyle === 2"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="title">除权类型</view> |
||||
|
<view class="top-options"> |
||||
|
<view class="option-btn" :class="{ 'active': exRights === 0 }" @click="exRights = 0"> |
||||
|
<text>除权</text> |
||||
|
<view class="active-dot" v-if="exRights === 0"></view> |
||||
|
</view> |
||||
|
<view class="option-btn" :class="{ 'active': exRights === 1 }" @click="exRights = 1"> |
||||
|
<text>普通</text> |
||||
|
<view class="active-dot" v-if="exRights === 1"></view> |
||||
|
</view> |
||||
|
<view class="option-btn" :class="{ 'active': exRights === 2 }" @click="exRights = 2"> |
||||
|
<text>加权</text> |
||||
|
<view class="active-dot" v-if="exRights === 2"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="title">涨跌颜色</view> |
||||
|
<view class="top-options"> |
||||
|
<view class="option-btn" :class="{ 'active': rfColor === 0 }" @click="rfColor = 0"> |
||||
|
<view class="color-icon"> |
||||
|
<img src="/static/my/greenRise.png" class="kline-icon" /> |
||||
|
</view> |
||||
|
<text>绿涨红跌</text> |
||||
|
<view class="active-dot" v-if="rfColor === 0"></view> |
||||
|
</view> |
||||
|
<view class="option-btn" :class="{ 'active': rfColor === 1 }" @click="rfColor = 1"> |
||||
|
<view class="color-icon"> |
||||
|
<img src="/static/my/redRise.png" class="kline-icon" /> |
||||
|
</view> |
||||
|
<text>红涨绿跌</text> |
||||
|
<view class="active-dot" v-if="rfColor === 1"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="title">副图指标个数</view> |
||||
|
<view class="top-options"> |
||||
|
<view class="option-btn" :class="{ 'active': indexCount === 0 }" @click="indexCount = 0"> |
||||
|
<text>1</text> |
||||
|
</view> |
||||
|
<view class="option-btn" :class="{ 'active': indexCount === 1 }" @click="indexCount = 1"> |
||||
|
<text>2</text> |
||||
|
</view> |
||||
|
<view class="option-btn" :class="{ 'active': indexCount === 2 }" @click="indexCount = 2"> |
||||
|
<text>3</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="indicator-title"> |
||||
|
<text>指标设置</text> |
||||
|
</view> |
||||
|
<view class="indicator-list"> |
||||
|
<view class="indicator-item" v-for="(item, index) in indicatorList" :key="index"> |
||||
|
<text class="indicator-text">{{ item }}</text> |
||||
|
<view class="indicator-icons"> |
||||
|
<img src="/static/my/setting.png" class="icon" /> |
||||
|
<img src="/static/my/menu.png" class="icon" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
<view style="height:10vh;background-color: white;"></view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const aStockBid = ref(0) // 股票竞价:Stock bidding |
||||
|
const kStyle = ref(0) // k线样式 |
||||
|
const exRights = ref(0) // 除权类型 除权:Ex-rights |
||||
|
const rfColor = ref(0) // 涨跌颜色 rise-fall |
||||
|
const indexCount = ref(0) // 副图指标个数 |
||||
|
const indicatorList = ref(['K线', '均线', '成交量', 'KDJ', 'MACD', 'RSI']) |
||||
|
|
||||
|
onMounted(() => { |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style scoped> |
||||
|
.time-share-title { |
||||
|
height: 4.5vh; |
||||
|
padding: 0 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.title { |
||||
|
height: 5.5vh; |
||||
|
padding: 0 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
font-size: 26rpx; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
.top-options { |
||||
|
height: 5.5vh; |
||||
|
display: flex; |
||||
|
padding: 0 40rpx; |
||||
|
} |
||||
|
|
||||
|
.option-btn { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
border: 1rpx solid #ddd; |
||||
|
border-radius: 8rpx; |
||||
|
margin: 0 10rpx; |
||||
|
padding: 15rpx 0; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.option-btn.active { |
||||
|
border-color: red; |
||||
|
} |
||||
|
|
||||
|
.active-dot { |
||||
|
width: 16rpx; |
||||
|
height: 16rpx; |
||||
|
background-color: red; |
||||
|
border-radius: 50%; |
||||
|
margin-left: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.kline-icon { |
||||
|
margin-right: 10rpx; |
||||
|
font-size: 32rpx; |
||||
|
} |
||||
|
|
||||
|
.color-icon { |
||||
|
margin-right: 10rpx; |
||||
|
display: flex; |
||||
|
gap: 4rpx; |
||||
|
} |
||||
|
|
||||
|
.indicator-title { |
||||
|
height: 6vh; |
||||
|
padding: 0 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.indicator-list { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
padding: 0 40rpx; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.indicator-item { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 7.5vh; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.indicator-text { |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.indicator-icons { |
||||
|
display: flex; |
||||
|
gap: 100rpx; |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
|
||||
|
.icon { |
||||
|
width: 28rpx; |
||||
|
height: 28rpx; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,62 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
<view class="top"> |
||||
|
<view class="top-list" @click="goToPush"> |
||||
|
<text>语言</text> |
||||
|
<text class="message" v-if="isMessage">通知已开启</text> |
||||
|
<text class="message" v-if="!isMessage">通知未开启</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const isMessage = ref(true) |
||||
|
|
||||
|
const goToPush = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url: '/pages/setting/push' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
margin-top: 1.5vh; |
||||
|
height: 7vh; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin: 0rpx 40rpx; |
||||
|
} |
||||
|
|
||||
|
.message { |
||||
|
margin-left: 60%; |
||||
|
font-size: 14px; |
||||
|
color: rgb(203, 203, 203); |
||||
|
} |
||||
|
|
||||
|
.arrow { |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,82 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
<view style="height:1.5vh;" /> |
||||
|
<view class="top"> |
||||
|
<view class="top-list"> |
||||
|
<text v-if="hasNew === true" class="label">已有新版本</text> |
||||
|
<text v-if="hasNew === false" class="label">已是最新版本</text> |
||||
|
<view class="right"> |
||||
|
<text style="font-size: 28rpx;">{{ version }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view style="height:1vh;" /> |
||||
|
|
||||
|
<view class="bottom"> |
||||
|
<button v-if="hasNew === true" class="bottom-btn">立即更新</button> |
||||
|
<button v-if="hasNew === false" class="bottom-btn" disabled |
||||
|
style="background-color: rgb(204,204,204);color:white;">暂无更新</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const hasNew = ref(true) |
||||
|
const version = ref('2.0') |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
height: 7vh; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin: 0rpx 40rpx; |
||||
|
} |
||||
|
|
||||
|
.label { |
||||
|
font-size: 28rpx; |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 11vh; |
||||
|
background-color: white; |
||||
|
padding: 0 50rpx; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.bottom-btn { |
||||
|
width: 670rpx; |
||||
|
height: 84rpx; |
||||
|
border-radius: 40rpx; |
||||
|
background-color: #000; |
||||
|
color: #fff; |
||||
|
font-size: 28rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,144 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view style="height:1.5vh;" /> |
||||
|
|
||||
|
<view class="title"> |
||||
|
<text class="label">确认新密码</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="top"> |
||||
|
<view class="top-list"> |
||||
|
<view class="left"> |
||||
|
<img src="/static/my/unlock.png" /> |
||||
|
<input type="password" :type="pwdType" placeholder="请输入新密码" class="input" /> |
||||
|
<img :src="pwdType === 1 ? '/static/my/hideEye.png' : '/static/my/openEye.png'" |
||||
|
@click="changeEye(1)" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="top-list"> |
||||
|
<view class="left"> |
||||
|
<img src="/static/my/unlock.png" /> |
||||
|
<input type="password" :type="pwdType2" placeholder="再次确认" class="input" /> |
||||
|
<img :src="pwdType === 1 ? '/static/my/hideEye.png' : '/static/my/openEye.png'" |
||||
|
@click="changeEye(2)" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<text class="tips">密码最少8位数</text> |
||||
|
</view> |
||||
|
|
||||
|
<view class="bottom"> |
||||
|
<button class="change-btn">确认</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
|
||||
|
const iSMT = ref(0) |
||||
|
const pwdType = ref('password') |
||||
|
const pwdType2 = ref('password') |
||||
|
|
||||
|
const changeEye = (type) => { |
||||
|
if (type === 1) { |
||||
|
pwdType.value = pwdType.value === 'password' ? 'text' : 'password' |
||||
|
} else { |
||||
|
pwdType2.value = pwdType2.value === 'password' ? 'text' : 'password' |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.title { |
||||
|
height: 8.5vh; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.label { |
||||
|
height: 8.5vh; |
||||
|
font-size: 40rpx; |
||||
|
font-weight: bold; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
padding: 0 60rpx; |
||||
|
} |
||||
|
|
||||
|
.top { |
||||
|
height: auto; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
margin: 0rpx 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.left { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.input { |
||||
|
flex: 1; |
||||
|
height: 70rpx; |
||||
|
font-size: 29rpx; |
||||
|
margin-left: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 22vh; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.change-btn { |
||||
|
height: 85rpx; |
||||
|
width: 610rpx; |
||||
|
padding: 0 20rpx; |
||||
|
background-color: black; |
||||
|
color: white; |
||||
|
border-radius: 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.img { |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
top: 50%; |
||||
|
transform: translateY(-50%); |
||||
|
} |
||||
|
|
||||
|
.tips { |
||||
|
font-size: 24rpx; |
||||
|
color: #999; |
||||
|
margin-top: 20rpx; |
||||
|
margin-left: 60rpx; |
||||
|
align-self: flex-start; |
||||
|
/* 这是左对齐 */ |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,171 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view class="tab"> |
||||
|
<view class="tab-item" :class="{active: activeTab === 'email'}" @click="activeTab = 'email'">邮箱</view> |
||||
|
<view class="tab-item" :class="{active: activeTab === 'phone'}" @click="activeTab = 'phone'">手机号</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="switch-tab"> |
||||
|
<view class="input-list" v-if="activeTab === 'email'"> |
||||
|
<image src="/static/my/changeEmail.png" mode="aspectFit"></image> |
||||
|
<input type="text" placeholder="请输入邮箱" class="input" /> |
||||
|
<button class="code-btn" :class="{disabled: gettingCode}" @click="getCode" :disabled="gettingCode"> |
||||
|
{{ gettingCode ? `重新发送 ${time}s` : '获取验证码' }} |
||||
|
</button> |
||||
|
</view> |
||||
|
|
||||
|
<view class="input-list" v-else> |
||||
|
<image src="/static/my/changeBindPhone.png" mode="aspectFit"></image> |
||||
|
<input type="number" placeholder="请输入手机号" class="input" /> |
||||
|
<button class="code-btn" :class="{disabled: gettingCode}" @click="getCode" :disabled="gettingCode"> |
||||
|
{{ gettingCode ? `重新发送 ${time}s` : '获取验证码' }} |
||||
|
</button> |
||||
|
</view> |
||||
|
|
||||
|
<view class="input-list"> |
||||
|
<image src="/static/my/verification.png" mode="aspectFit"></image> |
||||
|
<input type="text" placeholder="请输入验证码" class="input" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="btn-area"> |
||||
|
<button class="next-btn" @click="goToPwdNext">下一步</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
|
||||
|
const iSMT = ref(0) |
||||
|
const activeTab = ref('email') |
||||
|
const gettingCode = ref(false) |
||||
|
const time = ref(60) |
||||
|
|
||||
|
const getCode = () => { |
||||
|
if (gettingCode.value) return |
||||
|
gettingCode.value = true |
||||
|
|
||||
|
time.value = 60 |
||||
|
|
||||
|
const timer = setInterval(() => { |
||||
|
time.value-- |
||||
|
if (time.value <= 0) { |
||||
|
clearInterval(timer) |
||||
|
gettingCode.value = false |
||||
|
time.value = 60 |
||||
|
} |
||||
|
}, 1000) |
||||
|
} |
||||
|
|
||||
|
const goToPwdNext = () =>{ |
||||
|
uni.navigateTo({ |
||||
|
url:'../setting/nextPwd' |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 获取状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.tab { |
||||
|
display: flex; |
||||
|
height: 8vh; |
||||
|
background-color: #fff; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.tab-item { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
font-size: 32rpx; |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.tab-item.active { |
||||
|
color: #000; |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.tab-item.active::after { |
||||
|
content: ''; |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
width: 40rpx; |
||||
|
height: 6rpx; |
||||
|
background-color: #000;/* ????? */ |
||||
|
} |
||||
|
|
||||
|
.switch-tab { |
||||
|
background-color: #fff; |
||||
|
padding: 0 60rpx; |
||||
|
} |
||||
|
|
||||
|
.input-list { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
height: 7vh; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.input-list image { |
||||
|
width: 40rpx; |
||||
|
height: 40rpx; |
||||
|
margin-right: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.input { |
||||
|
flex: 1; |
||||
|
height: 14vh; |
||||
|
font-size: 28rpx; |
||||
|
} |
||||
|
|
||||
|
.code-btn { |
||||
|
width: 200rpx; |
||||
|
height: 60rpx; |
||||
|
font-size: 24rpx; |
||||
|
border-radius: 10rpx; |
||||
|
background-color: #eee; |
||||
|
color: #666; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.code-btn.disabled { |
||||
|
background-color: #ccc; |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.btn-area{ |
||||
|
height:8vh; |
||||
|
background-color: white; |
||||
|
padding-top: 120rpx; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.next-btn { |
||||
|
width: 610rpx; |
||||
|
height: 85rpx; |
||||
|
background-color: #000; |
||||
|
color: #fff; |
||||
|
font-size: 30rpx; |
||||
|
border-radius: 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,143 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
|
||||
|
<view style="height:1.5vh;" /> |
||||
|
|
||||
|
<view class="top"> |
||||
|
<view class="top-list"> |
||||
|
<view class="left"> |
||||
|
<img src="/static/my/bindedPhone.png" /> |
||||
|
<text class="label">已绑手机号:{{ phone }}</text> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="top-list"> |
||||
|
<view class="left"> |
||||
|
<img src="/static/my/changeBindPhone.png" /> |
||||
|
<text class="label">+86</text> |
||||
|
<input type="number" placeholder="请输入您的换绑手机号" class="input" /> |
||||
|
</view> |
||||
|
<view class="right"> |
||||
|
<button class="verification" :class="{ 'disabled': gettingCode }" @click="getVerification" |
||||
|
:disabled="gettingCode"> |
||||
|
{{ gettingCode ? `重新发送 ${time}s` : '获取验证码' }} |
||||
|
</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="top-list"> |
||||
|
<view class="left"> |
||||
|
<img src="/static/my/verification.png" /> |
||||
|
<input type="text" placeholder="请输入验证码" class="input" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="bottom"> |
||||
|
<button class="change-btn">换绑</button> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const phone = ref('15105421566') |
||||
|
const gettingCode = ref(false) |
||||
|
const time = ref(60) |
||||
|
|
||||
|
const getVerification = () => { |
||||
|
if (gettingCode.value) return |
||||
|
gettingCode.value = true |
||||
|
|
||||
|
time.value = 60 |
||||
|
|
||||
|
const timer = setInterval(() => { |
||||
|
time.value-- |
||||
|
if (time.value <= 0) { |
||||
|
clearInterval(timer) |
||||
|
gettingCode.value = false |
||||
|
} |
||||
|
}, 1000) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
height: auto; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
margin: 0rpx 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.left { |
||||
|
flex: 1; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.label { |
||||
|
font-size: 28rpx; |
||||
|
margin-left: 10rpx; |
||||
|
} |
||||
|
|
||||
|
.right { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.input { |
||||
|
flex: 1; |
||||
|
height: 70rpx; |
||||
|
font-size: 29rpx; |
||||
|
margin-left: 20rpx; |
||||
|
} |
||||
|
|
||||
|
.verification { |
||||
|
font-size: 24rpx; |
||||
|
border-radius: 10rpx; |
||||
|
background-color: rgb(230, 230, 230); |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 22vh; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
|
||||
|
.change-btn { |
||||
|
height: 85rpx; |
||||
|
width: 610rpx; |
||||
|
padding:0 20rpx; |
||||
|
background-color: black; |
||||
|
color: white; |
||||
|
border-radius: 40rpx; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,108 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
<view class="top"> |
||||
|
<view class="top-list"> |
||||
|
<text style="width:180rpx;">公共消息</text> |
||||
|
<text class="public">重大咨询、财经要闻等系统提醒</text> |
||||
|
<switch class="arrow switch-btn" /> |
||||
|
</view> |
||||
|
<view class="top-list"> |
||||
|
<text>字体大小</text> |
||||
|
<switch class="arrow switch-btn" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
|
||||
|
<view class="bottom"> |
||||
|
<view class="bottom-list"> |
||||
|
<text>盯盘预警</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
<view class="bottom-list"> |
||||
|
<text>订阅服务</text> |
||||
|
<text class="cache">45.5M</text> |
||||
|
<uni-icons type="arrowright" size="16" class="arrow" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
margin-top: 1.5vh; |
||||
|
height: 14vh; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin: 0 40rpx; |
||||
|
padding: 0 10rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.top-list:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.switch-btn { |
||||
|
width: 100rpx; |
||||
|
transform: scale(0.6); |
||||
|
transform-origin: center right; |
||||
|
} |
||||
|
|
||||
|
.public { |
||||
|
width: 450rpx; |
||||
|
margin-left: auto; |
||||
|
font-size: 10px; |
||||
|
color: rgb(203, 203, 203); |
||||
|
} |
||||
|
|
||||
|
.arrow { |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
|
||||
|
.bottom { |
||||
|
height: 13.5vh; |
||||
|
background-color: white; |
||||
|
margin-top: 1vh; |
||||
|
} |
||||
|
|
||||
|
.bottom-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
margin: 0 40rpx; |
||||
|
padding: 0 10rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.cache { |
||||
|
margin-left: 55%; |
||||
|
font-size: 14px; |
||||
|
color: rgb(203, 203, 203); |
||||
|
} |
||||
|
|
||||
|
.bottom-list:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,87 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
<view class="top"> |
||||
|
<view class="top-list"> |
||||
|
<text>自动选择</text> |
||||
|
<radio value="0" class="radio-btn" activeBackgroundColor="red" |
||||
|
:checked="selectedIndex === 0" @click="selectFont(0)" /> |
||||
|
</view> |
||||
|
<view class="top-list"> |
||||
|
<text>新加坡服务器</text> |
||||
|
<radio value="1" class="radio-btn" activeBackgroundColor="red" |
||||
|
:checked="selectedIndex === 1" @click="selectFont(1)" /> |
||||
|
</view> |
||||
|
<view class="top-list"> |
||||
|
<text>香港服务器</text> |
||||
|
<radio value="2" class="radio-btn" activeBackgroundColor="red" |
||||
|
:checked="selectedIndex === 2" @click="selectFont(2)" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const selectedIndex = ref(0) |
||||
|
|
||||
|
const selectFont = (index) => { |
||||
|
selectedIndex.value = index |
||||
|
console.log('看看选中状态',selectedIndex.value) |
||||
|
} |
||||
|
|
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.top { |
||||
|
margin-top: 1.5vh; |
||||
|
height: 21vh; |
||||
|
background-color: white; |
||||
|
} |
||||
|
|
||||
|
.top-list { |
||||
|
width: 630rpx; |
||||
|
height: 7vh; |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
margin: 0 40rpx; |
||||
|
padding: 0 10rpx; |
||||
|
border-bottom: 1rpx solid #eee; |
||||
|
} |
||||
|
|
||||
|
.top-list:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.switch-btn { |
||||
|
width: 100rpx; |
||||
|
transform: scale(0.6); |
||||
|
transform-origin: center right; |
||||
|
} |
||||
|
|
||||
|
.public { |
||||
|
width: 450rpx; |
||||
|
margin-left: auto; |
||||
|
font-size: 10px; |
||||
|
color: rgb(203, 203, 203); |
||||
|
} |
||||
|
|
||||
|
.arrow { |
||||
|
margin-left: auto; |
||||
|
} |
||||
|
|
||||
|
.radio-btn { |
||||
|
margin-left: auto; |
||||
|
transform: scale(0.6); |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,111 @@ |
|||||
|
<template> |
||||
|
<view class="all"> |
||||
|
<img class="img-share" src="/static/my/shareBackground.png" /> |
||||
|
<img class="img-greenBack" src="/static/my/greenBackground.png" /> |
||||
|
<img class="img-QRcode" src="/static/my/QRcode.png" /> |
||||
|
<img class="img-award" src="/static/my/award.png" /> |
||||
|
<img class="img-myFriends" src="/static/my/myFriends.png" /> |
||||
|
<img class="img-friends" src="/static/my/shareFriends.png" /> |
||||
|
<text class="jwcode">{{ jwcode }}</text> |
||||
|
<button class="invite">立即邀请</button> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref |
||||
|
} from 'vue' |
||||
|
|
||||
|
const jwcode = ref('90047681') |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.all { |
||||
|
position: relative; |
||||
|
width: 750rpx; |
||||
|
height: auto; |
||||
|
} |
||||
|
|
||||
|
.img-share { |
||||
|
width: 750rpx; |
||||
|
height: 2118rpx; |
||||
|
position: absolute; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
z-index: 1; |
||||
|
} |
||||
|
|
||||
|
.img-QRcode{ |
||||
|
width:320rpx; |
||||
|
height:320rpx; |
||||
|
position:absolute; |
||||
|
top:26vh; |
||||
|
left:215rpx; |
||||
|
z-index: 3; |
||||
|
} |
||||
|
|
||||
|
.img-greenBack { |
||||
|
width: 670rpx; |
||||
|
height: 1740rpx; |
||||
|
position: absolute; |
||||
|
top: 16vh; |
||||
|
/* 为什么要用这个替代 margin-top */ |
||||
|
left: 40rpx; |
||||
|
/* 还有 padding-left */ |
||||
|
z-index: 2; |
||||
|
} |
||||
|
|
||||
|
.img-friends { |
||||
|
width: 602rpx; |
||||
|
height: 840rpx; |
||||
|
position: absolute; |
||||
|
top: 68vh; |
||||
|
left: 74rpx; |
||||
|
z-index: 3; |
||||
|
} |
||||
|
|
||||
|
.img-award { |
||||
|
width: 300rpx; |
||||
|
height: 120rpx; |
||||
|
position: absolute; |
||||
|
top: 61vh; |
||||
|
left: 75rpx; |
||||
|
z-index: 3; |
||||
|
} |
||||
|
|
||||
|
.img-myFriends { |
||||
|
width: 300rpx; |
||||
|
height: 88rpx; |
||||
|
position: absolute; |
||||
|
top: 61vh; |
||||
|
right: 75rpx; |
||||
|
z-index: 3; |
||||
|
} |
||||
|
|
||||
|
.jwcode { |
||||
|
width: 320rpx; |
||||
|
height: 38rpx; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
position: absolute; |
||||
|
top: 19vh; |
||||
|
left: 212rpx; |
||||
|
z-index: 999; |
||||
|
} |
||||
|
|
||||
|
.invite { |
||||
|
width: 320rpx; |
||||
|
height: 80rpx; |
||||
|
border-radius: 40rpx; |
||||
|
background-color: black; |
||||
|
color:white; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
position: absolute; |
||||
|
top: 50.7vh; |
||||
|
left: 212rpx; |
||||
|
z-index: 999; |
||||
|
} |
||||
|
</style> |
||||
@ -0,0 +1,64 @@ |
|||||
|
<template> |
||||
|
<view class="main"> |
||||
|
<view :style="{height:iSMT+'px'}"></view> |
||||
|
<view class="theme"> |
||||
|
<view class="left"> |
||||
|
<image class="img-theme" src="/static/my/whiteTheme.png" mode="widthFix" /> |
||||
|
<radio value="0" class="radio-btn" activeBackgroundColor="red" :checked="selectedIndex === 0" |
||||
|
@click="selectFont(0)" /> |
||||
|
</view> |
||||
|
<view class="left"> |
||||
|
<image class="img-theme" src="/static/my/blackTheme.png" mode="widthFix" /> |
||||
|
<radio value="1" class="radio-btn" activeBackgroundColor="red" :checked="selectedIndex === 1" |
||||
|
@click="selectFont(1)" /> |
||||
|
</view> |
||||
|
</view> |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
import { |
||||
|
ref, |
||||
|
onMounted |
||||
|
} from 'vue' |
||||
|
const iSMT = ref(0) |
||||
|
const selectedIndex = ref(0) |
||||
|
|
||||
|
const selectFont = (index) => { |
||||
|
selectedIndex.value = index |
||||
|
console.log('看看选中状态', selectedIndex.value) |
||||
|
} |
||||
|
onMounted(() => { |
||||
|
// 状态栏高度 |
||||
|
iSMT.value = uni.getSystemInfoSync().statusBarHeight; |
||||
|
console.log('看看高度', iSMT.value) |
||||
|
}) |
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
.theme { |
||||
|
margin-top: 1.5vh; |
||||
|
height: 34vh; |
||||
|
background-color: white; |
||||
|
display: flex; |
||||
|
justify-content: space-around; |
||||
|
} |
||||
|
|
||||
|
.img-theme { |
||||
|
width: 316rpx; |
||||
|
height: 362rpx; |
||||
|
} |
||||
|
|
||||
|
.left { |
||||
|
width: 350rpx; |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.radio-btn { |
||||
|
margin-top: 36rpx; |
||||
|
transform: scale(0.8); |
||||
|
} |
||||
|
</style> |
||||
1054
pages/start/Registration/Registration.vue
File diff suppressed because it is too large
View File
1341
pages/start/Registration/list.js
File diff suppressed because it is too large
View File
@ -0,0 +1,13 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
用户协议 |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
|
||||
|
</style> |
||||
@ -0,0 +1,56 @@ |
|||||
|
<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"; |
||||
|
import { useUserStore } from "../../../stores/modules/userInfo"; |
||||
|
const title = ref("请先登录"); |
||||
|
const loginPrompt = ref(null); |
||||
|
|
||||
|
const userStore = useUserStore(); |
||||
|
function showLoginPrompt() { |
||||
|
userStore.clearUserInfo(); |
||||
|
} |
||||
|
|
||||
|
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
1190
pages/start/login/login.vue
File diff suppressed because it is too large
View File
@ -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} |
||||
@ -0,0 +1,13 @@ |
|||||
|
<template> |
||||
|
<view> |
||||
|
隐私政策 |
||||
|
</view> |
||||
|
</template> |
||||
|
|
||||
|
<script setup> |
||||
|
|
||||
|
</script> |
||||
|
|
||||
|
<style> |
||||
|
|
||||
|
</style> |
||||
1012
pages/start/recoverPassword/recoverPassword.vue
File diff suppressed because it is too large
View File
@ -0,0 +1,170 @@ |
|||||
|
<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"; |
||||
|
import { ref, reactive, toRefs, watch } from "vue"; |
||||
|
|
||||
|
|
||||
|
const type = ref(""); |
||||
|
|
||||
|
function toRegistration() { |
||||
|
uni.redirectTo({ |
||||
|
url: "/pages/start/Registration/Registration", |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function toLogin() { |
||||
|
uni.redirectTo({ |
||||
|
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> |
||||
@ -0,0 +1,73 @@ |
|||||
|
<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"; |
||||
|
import { useUserStore } from "../../../stores/modules/userInfo"; |
||||
|
import { useDeviceStore } from "../../../stores/modules/deviceInfo"; |
||||
|
|
||||
|
onShow(() => { |
||||
|
const deviceInfo = useDeviceStore(); |
||||
|
// 获取设备ID |
||||
|
uni.getSystemInfo({ |
||||
|
success: (res) => { |
||||
|
deviceInfo.setDeviceInfo(res) |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
setTimeout(() => { |
||||
|
const userStore = useUserStore(); |
||||
|
if (!userStore.userInfo) |
||||
|
uni.redirectTo({ |
||||
|
url: "/pages/start/select/select", |
||||
|
animationType: "slide-in-right", |
||||
|
animationDuration: 1000, |
||||
|
}); |
||||
|
else { |
||||
|
uni.redirectTo({ |
||||
|
url: "/pages/home/home", |
||||
|
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> |
||||
@ -0,0 +1,138 @@ |
|||||
|
{ |
||||
|
"loginSuccessByEmail": { |
||||
|
"code": 200, |
||||
|
"message": "c3e9ed50ad72073b94dfb04860562b58", |
||||
|
"data": { |
||||
|
"loginType": null, |
||||
|
"device": "unknown", |
||||
|
"dccode": "90047686", |
||||
|
"account": null, |
||||
|
"password": null, |
||||
|
"verifyCode": null, |
||||
|
"useCode": false, |
||||
|
"idToken": null, |
||||
|
"token": "c3e9ed50ad72073b94dfb04860562b58", |
||||
|
"market": "新加坡", |
||||
|
"phone": "17861484516", |
||||
|
"email": "q614588746@163.com", |
||||
|
"language": "中文", |
||||
|
"avatar": "123" |
||||
|
} |
||||
|
}, |
||||
|
"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" |
||||
|
} |
||||
|
} |
||||
|
After Width: 750 | Height: 198 | Size: 35 KiB |
|
After Width: 750 | Height: 198 | Size: 36 KiB |
|
After Width: 750 | Height: 198 | Size: 37 KiB |
|
After Width: 750 | Height: 198 | Size: 35 KiB |
|
After Width: 200 | Height: 200 | Size: 4.8 KiB |
|
After Width: 305 | Height: 200 | Size: 7.9 KiB |
|
After Width: 200 | Height: 200 | Size: 4.8 KiB |
|
After Width: 48 | Height: 48 | Size: 1.6 KiB |
|
After Width: 24 | Height: 24 | Size: 232 B |
|
After Width: 28 | Height: 31 | Size: 894 B |
|
After Width: 16 | Height: 15 | Size: 797 B |
|
After Width: 40 | Height: 40 | Size: 1.9 KiB |
|
After Width: 40 | Height: 40 | Size: 2.6 KiB |
|
After Width: 40 | Height: 40 | Size: 1.7 KiB |
|
After Width: 40 | Height: 40 | Size: 1.5 KiB |
|
After Width: 200 | Height: 200 | Size: 3.1 KiB |
|
After Width: 200 | Height: 200 | Size: 4.4 KiB |
|
After Width: 18 | Height: 18 | Size: 523 B |
|
After Width: 9 | Height: 9 | Size: 274 B |
|
After Width: 16 | Height: 16 | Size: 522 B |
|
After Width: 34 | Height: 34 | Size: 292 B |
|
After Width: 100 | Height: 70 | Size: 2.1 KiB |
|
After Width: 100 | Height: 50 | Size: 170 B |
|
After Width: 100 | Height: 67 | Size: 2.6 KiB |
|
After Width: 100 | Height: 67 | Size: 2.0 KiB |
|
After Width: 100 | Height: 50 | Size: 1.3 KiB |
|
After Width: 100 | Height: 71 | Size: 1.7 KiB |
|
After Width: 100 | Height: 50 | Size: 122 B |
|
After Width: 100 | Height: 67 | Size: 610 B |
|
After Width: 100 | Height: 67 | Size: 1.4 KiB |
|
After Width: 100 | Height: 100 | Size: 6.0 KiB |
|
After Width: 100 | Height: 63 | Size: 991 B |
|
After Width: 100 | Height: 50 | Size: 2.0 KiB |
|
After Width: 100 | Height: 67 | Size: 133 B |