14 changed files with 2170 additions and 19 deletions
-
134components/login-prompt.vue
-
7main.js
-
6package-lock.json
-
93pages.json
-
678pages/deepMate/deepMate.vue
-
399pages/start/Registration/Registration.vue
-
13pages/start/agreement/agreement.vue
-
134pages/start/components/login-prompt/login-prompt.vue
-
55pages/start/index/index.vue
-
371pages/start/login/login.vue
-
13pages/start/privacy/privacy.vue
-
194pages/start/select/select.vue
-
40pages/start/startup/startup.vue
-
18vue.config.js
@ -0,0 +1,134 @@ |
|||
<template> |
|||
<view class="login-prompt" v-if="showPrompt"> |
|||
<view class="mask" :class="{ 'mask-show': showAnimation }" @click="hide"></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> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, nextTick } from 'vue'; |
|||
|
|||
// 定义响应式数据 |
|||
const showPrompt = ref(false); |
|||
const showAnimation = ref(false); |
|||
|
|||
// 显示弹窗 |
|||
const show = () => { |
|||
showPrompt.value = true; |
|||
// 在下一帧触发动画 |
|||
nextTick(() => { |
|||
setTimeout(() => { |
|||
showAnimation.value = true; |
|||
}, 10); |
|||
}); |
|||
}; |
|||
|
|||
// 隐藏弹窗 |
|||
const hide = () => { |
|||
showAnimation.value = false; |
|||
// 等待动画结束后再隐藏 |
|||
setTimeout(() => { |
|||
showPrompt.value = false; |
|||
}, 300); |
|||
}; |
|||
|
|||
// 跳转到登录页面 |
|||
const goLogin = () => { |
|||
uni.navigateTo({ |
|||
url: '/pages/login/login' |
|||
}); |
|||
hide(); |
|||
}; |
|||
|
|||
// 以访客身份继续 |
|||
const continueAsVisitor = () => { |
|||
// 设置访客模式 |
|||
uni.setStorageSync('visitorMode', true); |
|||
hide(); |
|||
}; |
|||
|
|||
// 暴露方法给外部使用 |
|||
defineExpose({ |
|||
show, |
|||
hide |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.login-prompt { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: 999; |
|||
} |
|||
|
|||
.mask { |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
background-color: rgba(0, 0, 0, 0.8); |
|||
opacity: 0; |
|||
transition: opacity 0.3s ease; |
|||
} |
|||
|
|||
.mask.mask-show { |
|||
opacity: 1; |
|||
} |
|||
|
|||
.prompt-content { |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
height: 300rpx; |
|||
border-radius: 20rpx 20rpx 0 0; |
|||
background-color: white; |
|||
padding: 20rpx 30rpx; |
|||
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: left; |
|||
font-size: 28rpx; |
|||
font-weight: 700; |
|||
color: #333; |
|||
margin-top: 10rpx; |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.login-btn { |
|||
width: 100%; |
|||
height: 80rpx; |
|||
background-color:rgb(35, 84, 230); |
|||
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; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"name": "deepChartVueApp", |
|||
"lockfileVersion": 3, |
|||
"requires": true, |
|||
"packages": {} |
|||
} |
|||
@ -0,0 +1,678 @@ |
|||
<template> |
|||
<view class="deepMate-page"> |
|||
<!-- 顶部导航栏 --> |
|||
<view class="header" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"> |
|||
<view class="header-left"> |
|||
<image src="../../static/icons/headset.png" class="icon"></image> |
|||
</view> |
|||
<view class="header-center"> |
|||
<text class="title">DeepMate</text> |
|||
</view> |
|||
<view class="header-right"> |
|||
<image src="../../static/icons/bell.png" class="icon"></image> |
|||
<image src="../../static/icons/clock.png" class="icon"></image> |
|||
<!-- 新增新会话按钮 |
|||
<button class="new-chat-button" @click="newChat"> |
|||
<text class="new-chat-text">新会话</text> |
|||
</button> --> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 主要内容区域 --> |
|||
<view class="main-content"> |
|||
<!-- 机器人头像和欢迎语 --> |
|||
<view class="robot-container" v-if="messages.length === 0"> |
|||
<image src="/static/robot.png" class="robot-avatar"></image> |
|||
<view class="welcome-message"> |
|||
<text class="greeting">Hi, 我是您的股市随身顾问~</text> |
|||
<text class="description">个股诊断、市场情绪解读,都可以找我。</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 功能标签栏 --> |
|||
<view class="function-tabs" v-if="messages.length === 0"> |
|||
<view class="tab-item ">个股诊断</view> |
|||
<view class="tab-item">市场情绪温度计</view> |
|||
<view class="tab-item">买卖时机提示</view> |
|||
<view class="tab-item">个股</view> |
|||
</view> |
|||
|
|||
<!-- 特斯拉推荐卡片 --> |
|||
<view class="recommend-card" v-if="messages.length === 0"> |
|||
<view class="card-content"> |
|||
<image src="../../static/images/tesla-logo.png" class="logo"></image> |
|||
<view class="card-text"> |
|||
<text class="main-question">当前特斯拉该如何布局?</text> |
|||
<text class="stock-code">TSLA</text> |
|||
</view> |
|||
<image src="/static/icons/arrow-right.png" class="arrow-icon"></image> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 可能感兴趣的话题 --> |
|||
<view v-if="messages.length === 0" class="interest-section"> |
|||
<text class="section-title">- 您可能感兴趣 -</text> |
|||
<view class="topics-list"> |
|||
<view class="topic-item" v-for="topic in hotTopics" :key="topic.id"> |
|||
<image |
|||
:src="topic.icon" |
|||
class="tag-icon" |
|||
></image> |
|||
<text class="topic-text" @click="sendMessageList(topic.text)">{{ topic.text }}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 聊天区域 --> |
|||
<view class="chat-container" v-if="messages.length > 0"> |
|||
<view class="message-list" id="messageList"> |
|||
<view |
|||
v-for="(message, index) in messages" |
|||
:key="index" |
|||
:class=" |
|||
message.isUser ? 'message user-message' : 'message bot-message' |
|||
" |
|||
> |
|||
<!-- 会话图标 --> |
|||
<text |
|||
:class=" |
|||
message.isUser |
|||
? 'fa-solid fa-user message-icon' |
|||
: 'fa-solid fa-robot message-icon' |
|||
" |
|||
></text> |
|||
<!-- 会话内容 --> |
|||
<view class="message-content"> |
|||
<text class="message-text">{{ message.content }}</text> |
|||
<!-- loading --> |
|||
<view |
|||
class="loading-dots" |
|||
v-if="message.isThinking || message.isTyping" |
|||
> |
|||
<text class="dot"></text> |
|||
<text class="dot"></text> |
|||
<text class="dot"></text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 输入框区域 --> |
|||
<view class="input-area"> |
|||
<view class="input-wrapper"> |
|||
<image src="../../static/icons/mic.png" class="mic-icon"></image> |
|||
<input |
|||
type="text" |
|||
placeholder="请输入股票代码/名称,获取AI洞察" |
|||
class="input-field" |
|||
v-model="inputMessage" |
|||
@confirm="sendMessage" |
|||
/> |
|||
<button class="send-button" @click="sendMessage" :disabled="isSending"> |
|||
<image |
|||
src="/static/icons/send.png" |
|||
class="send-icon" |
|||
></image> |
|||
</button> |
|||
</view> |
|||
<text class="disclaimer" |
|||
>以上数据由AI生成,不作为最终投资建议,决策需独立!</text |
|||
> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
const { safeAreaInsets } = uni.getSystemInfoSync(); |
|||
|
|||
import { ref, onMounted, nextTick } from "vue"; |
|||
|
|||
const inputMessage = ref(""); |
|||
const isSending = ref(false); |
|||
const uuid = ref(""); |
|||
const messages = ref([]); |
|||
const hotTopics = ref([ |
|||
{ |
|||
id: 1, |
|||
text: '英伟达(NVDA)股票情绪温度?', |
|||
icon: '../../static/icons/hot-tag.png' |
|||
}, |
|||
{ |
|||
id: 2, |
|||
text: '博通(AVGO)明天还能涨吗?', |
|||
icon: '../../static/icons/hot-tag.png' |
|||
}, |
|||
{ |
|||
id: 3, |
|||
text: '为什么Fluence Energy(FLNC)会暴涨?', |
|||
icon: '../../static/icons/hot-tag.png' |
|||
}, |
|||
{ |
|||
id: 4, |
|||
text: '为什么Fluence Energy(FLNC)会暴涨?', |
|||
icon: '../../static/icons/hot-tag.png' |
|||
} |
|||
]); |
|||
|
|||
// 初始化 |
|||
onMounted(() => { |
|||
initUUID(); |
|||
// 如果有历史消息,滚动到底部 |
|||
if (messages.value.length > 0) { |
|||
nextTick(() => { |
|||
scrollToBottom(); |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
// 初始化 UUID |
|||
const initUUID = () => { |
|||
let storedUUID = uni.getStorageSync('user_uuid'); |
|||
if (!storedUUID) { |
|||
storedUUID = generateUUID(); |
|||
uni.setStorageSync('user_uuid', storedUUID); |
|||
} |
|||
uuid.value = storedUUID; |
|||
}; |
|||
|
|||
// 生成简单UUID |
|||
const generateUUID = () => { |
|||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { |
|||
var r = Math.random() * 16 | 0, |
|||
v = c == 'x' ? r : (r & 0x3 | 0x8); |
|||
return v.toString(16); |
|||
}); |
|||
}; |
|||
|
|||
// 新会话 |
|||
const newChat = () => { |
|||
messages.value = []; |
|||
uni.removeStorageSync('user_uuid'); |
|||
initUUID(); |
|||
}; |
|||
|
|||
// 发送消息 |
|||
const sendMessage = () => { |
|||
if (inputMessage.value.trim() === "" || isSending.value) return; |
|||
|
|||
const userMessage = { |
|||
content: inputMessage.value, |
|||
isUser: true, |
|||
isThinking: false, |
|||
isTyping: false |
|||
}; |
|||
|
|||
messages.value.push(userMessage); |
|||
inputMessage.value = ""; |
|||
|
|||
// 滚动到底部 |
|||
nextTick(() => { |
|||
scrollToBottom(); |
|||
}); |
|||
|
|||
// 模拟机器人回复 |
|||
simulateBotResponse(userMessage.content); |
|||
}; |
|||
|
|||
|
|||
// 发送消息 |
|||
const sendMessageList = (listMessage) => { |
|||
|
|||
console.log(listMessage); |
|||
|
|||
|
|||
const userMessage = { |
|||
content: listMessage, |
|||
isUser: true, |
|||
isThinking: false, |
|||
isTyping: false |
|||
}; |
|||
|
|||
messages.value.push(userMessage); |
|||
inputMessage.value = ""; |
|||
|
|||
// 滚动到底部 |
|||
nextTick(() => { |
|||
scrollToBottom(); |
|||
}); |
|||
|
|||
// 模拟机器人回复 |
|||
simulateBotResponse(userMessage.content); |
|||
}; |
|||
|
|||
// 模拟机器人回复 |
|||
const simulateBotResponse = (userMessage) => { |
|||
isSending.value = true; |
|||
|
|||
// 添加机器人加载消息 |
|||
const botMsg = { |
|||
content: "", |
|||
isUser: false, |
|||
isTyping: true, |
|||
isThinking: false |
|||
}; |
|||
|
|||
messages.value.push(botMsg); |
|||
|
|||
// 滚动到底部 |
|||
nextTick(() => { |
|||
scrollToBottom(); |
|||
}); |
|||
|
|||
// 模拟流式响应 |
|||
let responseText = `我已经收到您的消息: "${userMessage}"。作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?`; |
|||
let index = 0; |
|||
|
|||
const typeWriter = () => { |
|||
if (index < responseText.length) { |
|||
botMsg.content += responseText.charAt(index); |
|||
index++; |
|||
|
|||
// 滚动到底部 |
|||
scrollToBottom(); |
|||
|
|||
setTimeout(typeWriter, 30); |
|||
} else { |
|||
botMsg.isTyping = false; |
|||
isSending.value = false; |
|||
} |
|||
}; |
|||
|
|||
setTimeout(typeWriter, 500); |
|||
}; |
|||
|
|||
// 滚动到底部 |
|||
const scrollToBottom = () => { |
|||
const query = uni.createSelectorQuery(); |
|||
query.select('#messageList').boundingClientRect(); |
|||
query.selectViewport().scrollOffset(); |
|||
|
|||
query.exec((res) => { |
|||
if (res[0] && res[1]) { |
|||
uni.pageScrollTo({ |
|||
scrollTop: res[0].height, |
|||
duration: 100 |
|||
}); |
|||
} |
|||
}); |
|||
}; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.deepMate-page { |
|||
display: flex; |
|||
flex-direction: column; |
|||
height: 100vh; |
|||
background-color: #ffffff; |
|||
padding: 20rpx; |
|||
} |
|||
|
|||
.header { |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 20rpx 30rpx; |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
.header-left, |
|||
.header-right { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.header-left .icon, |
|||
.header-right .icon { |
|||
width: 40rpx; |
|||
height: 40rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.header-center .title { |
|||
|
|||
|
|||
font-size: 36rpx; |
|||
font-weight: bold; |
|||
color: #333333; |
|||
} |
|||
|
|||
.new-chat-button { |
|||
background-color: #ff6600; |
|||
border: none; |
|||
border-radius: 8rpx; |
|||
padding: 10rpx 20rpx; |
|||
} |
|||
|
|||
.new-chat-text { |
|||
color: white; |
|||
font-size: 24rpx; |
|||
} |
|||
|
|||
.main-content { |
|||
flex: 1; |
|||
padding: 30rpx; |
|||
overflow-y: auto; |
|||
margin-bottom: 120rpx; |
|||
} |
|||
|
|||
.robot-container { |
|||
display: flex; |
|||
align-items: center; |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.robot-avatar { |
|||
width: 120rpx; |
|||
height: 120rpx; |
|||
border-radius: 50%; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.welcome-message { |
|||
flex: 1; |
|||
} |
|||
|
|||
.greeting { |
|||
font-size: 32rpx; |
|||
font-weight: bold; |
|||
color: #333333; |
|||
line-height: 48rpx; |
|||
} |
|||
|
|||
.description { |
|||
display: block; |
|||
font-size: 26rpx; |
|||
color: #666666; |
|||
line-height: 36rpx; |
|||
margin-top: 10rpx; |
|||
} |
|||
|
|||
.function-tabs { |
|||
display: flex; |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.tab-item { |
|||
padding: 5rpx 20rpx; |
|||
border-radius: 20rpx; |
|||
font-size: 20rpx; |
|||
font-weight: 700; |
|||
color: #666666; |
|||
background-color: #f0f0f0; |
|||
margin-right: 20rpx; |
|||
transition: all 0.3s; |
|||
} |
|||
|
|||
.tab-item.active { |
|||
color: #ff6600; |
|||
background-color: #fff; |
|||
border: 1rpx solid #ff6600; |
|||
} |
|||
|
|||
.recommend-card { |
|||
background: linear-gradient(180deg, #fee7ed 0%, #ffffff 100%); |
|||
border-radius: 20rpx; |
|||
padding: 30rpx; |
|||
margin-bottom: 30rpx; |
|||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
.card-content { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
.logo { |
|||
width: 80rpx; |
|||
height: 80rpx; |
|||
background-color: #ff0000; |
|||
border-radius: 10rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.card-text { |
|||
flex: 1; |
|||
} |
|||
|
|||
.main-question { |
|||
font-size: 32rpx; |
|||
color: #333333; |
|||
line-height: 48rpx; |
|||
} |
|||
|
|||
.stock-code { |
|||
display: block; |
|||
font-size: 24rpx; |
|||
color: #ff3b30; |
|||
background-color: #ffffff; |
|||
padding: 2rpx 15rpx; |
|||
border-radius: 12rpx; |
|||
margin-top: 8rpx; |
|||
width: fit-content; |
|||
border: 1rpx solid #ff3b30; |
|||
} |
|||
|
|||
.arrow-icon { |
|||
width: 32rpx; |
|||
height: 32rpx; |
|||
} |
|||
|
|||
.interest-section { |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.section-title { |
|||
display: block; |
|||
text-align: center; |
|||
font-size: 26rpx; |
|||
color: #666666; |
|||
margin-bottom: 20rpx; |
|||
} |
|||
|
|||
.topics-list { |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 15rpx; |
|||
} |
|||
|
|||
.topic-item { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 15rpx 20rpx; |
|||
background-color: #f0f0f0; |
|||
border-radius: 15rpx; |
|||
width: fit-content; |
|||
} |
|||
|
|||
.tag-icon { |
|||
width: 24rpx; |
|||
height: 24rpx; |
|||
margin-right: 10rpx; |
|||
} |
|||
|
|||
.topic-text { |
|||
font-size: 28rpx; |
|||
color: #333333; |
|||
flex: 1; |
|||
} |
|||
|
|||
/* 聊天区域样式 */ |
|||
.chat-container { |
|||
margin-top: 30rpx; |
|||
border-radius: 10rpx; |
|||
height: fit-content; |
|||
/* overflow-y: auto; */ |
|||
} |
|||
|
|||
.message-list { |
|||
/* padding: 20rpx; */ |
|||
} |
|||
|
|||
.message { |
|||
display: flex; |
|||
align-items: flex-start; |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.user-message { |
|||
flex-direction: row-reverse; |
|||
} |
|||
|
|||
.message-icon { |
|||
font-size: 24rpx; |
|||
margin: 0 10rpx; |
|||
padding: 10rpx; |
|||
border-radius: 50%; |
|||
background-color: #ddd; |
|||
width: 40rpx; |
|||
height: 40rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.user-message .message-icon { |
|||
background-color: #007aff; |
|||
color: white; |
|||
} |
|||
|
|||
.bot-message .message-icon { |
|||
background-color: #34c759; |
|||
color: white; |
|||
} |
|||
|
|||
.message-content { |
|||
max-width: 70%; |
|||
position: relative; |
|||
} |
|||
|
|||
.user-message .message-content { |
|||
background-color: #007aff; |
|||
border-radius: 10rpx; |
|||
padding: 15rpx; |
|||
} |
|||
|
|||
.bot-message .message-content { |
|||
background-color: #f0f0f0; |
|||
border-radius: 10rpx; |
|||
padding: 15rpx; |
|||
} |
|||
|
|||
.message-text { |
|||
font-size: 28rpx; |
|||
line-height: 40rpx; |
|||
} |
|||
|
|||
.user-message .message-text { |
|||
color: white; |
|||
} |
|||
|
|||
.bot-message .message-text { |
|||
color: #333; |
|||
} |
|||
|
|||
.loading-dots { |
|||
display: flex; |
|||
align-items: center; |
|||
padding-top: 10rpx; |
|||
} |
|||
|
|||
.dot { |
|||
width: 10rpx; |
|||
height: 10rpx; |
|||
background-color: #666; |
|||
border-radius: 50%; |
|||
margin: 0 4rpx; |
|||
animation: loading 1.4s infinite ease-in-out both; |
|||
} |
|||
|
|||
.user-message .dot { |
|||
background-color: white; |
|||
} |
|||
|
|||
.dot:nth-child(1) { |
|||
animation-delay: -0.32s; |
|||
} |
|||
|
|||
.dot:nth-child(2) { |
|||
animation-delay: -0.16s; |
|||
} |
|||
|
|||
@keyframes loading { |
|||
0%, |
|||
80%, |
|||
100% { |
|||
transform: scale(0); |
|||
} |
|||
40% { |
|||
transform: scale(1); |
|||
} |
|||
} |
|||
|
|||
.input-area { |
|||
position: fixed; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
padding: 0 40rpx 80rpx 40rpx; |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
.input-wrapper { |
|||
position: relative; |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 15rpx 20rpx; |
|||
background-color: rgb(220, 31, 29); |
|||
border-radius: 100rpx; |
|||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); |
|||
height: 50rpx; |
|||
} |
|||
|
|||
.mic-icon { |
|||
width: 36rpx; |
|||
height: 36rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.input-field { |
|||
flex: 1; |
|||
font-size: 28rpx; |
|||
color: #ffffff; |
|||
background: none; |
|||
border: none; |
|||
outline: none; |
|||
} |
|||
|
|||
.input-field::placeholder { |
|||
color: #ffffff !important; |
|||
opacity: 1; |
|||
} |
|||
|
|||
.send-button { |
|||
background: none; |
|||
border: none; |
|||
padding: 0; |
|||
margin-left: 20rpx; |
|||
} |
|||
|
|||
.send-icon { |
|||
width: 36rpx; |
|||
height: 36rpx; |
|||
} |
|||
|
|||
.disclaimer { |
|||
font-size: 15rpx; |
|||
color: #999999; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-top: 15rpx; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,399 @@ |
|||
<template> |
|||
<view class="login-registration-container"> |
|||
<!-- 自定义导航栏 --> |
|||
<view class="custom-navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"> |
|||
<view class="nav-left"> |
|||
<text class="back-btn" @click="goToLogin"><</text> |
|||
</view> |
|||
<view class="nav-right"> |
|||
<text class="headphone-btn">🎧</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- Logo --> |
|||
<image class="logo" src="/static/logo.png" mode="aspectFit"></image> |
|||
|
|||
<!-- 欢迎语 --> |
|||
<text class="welcome-text">欢迎来到 DeepChart</text> |
|||
|
|||
<!-- 邮箱/手机号切换 --> |
|||
<view class="switch-container"> |
|||
<text |
|||
class="switch-item" |
|||
:class="{ active: switchType === 'Email' }" |
|||
@click="switchEmail">邮箱</text> |
|||
<text |
|||
class="switch-item" |
|||
:class="{ active: switchType === 'Phone' }" |
|||
@click="switchPhone">手机号</text> |
|||
</view> |
|||
|
|||
<!-- 输入框 --> |
|||
<view class="input-container"> |
|||
<input |
|||
v-if="switchType === 'Email'" |
|||
class="input-field" |
|||
type="text" |
|||
placeholder="输入邮箱地址" |
|||
v-model="email" |
|||
/> |
|||
<input |
|||
v-else |
|||
class="input-field" |
|||
type="text" |
|||
placeholder="输入手机号" |
|||
v-model="phone" |
|||
/> |
|||
</view> |
|||
|
|||
<!-- 用户协议 --> |
|||
<view class="agreement-container"> |
|||
<checkbox class="checkbox" @click="checkboxClick"/> |
|||
<text class="agreement-text" |
|||
>接受 <text class="link" @click="openAgreement">用户协议</text> 和 |
|||
<text class="link" @click="openPrivacy">隐私政策</text></text |
|||
> |
|||
</view> |
|||
|
|||
<!-- 注册按钮 --> |
|||
<button class="register-btn" @click="register">注册</button> |
|||
|
|||
<!-- 或者 --> |
|||
<text class="or-text">或者</text> |
|||
|
|||
<!-- 第三方登录 --> |
|||
<view class="third-party-login"> |
|||
<view class="third-party-btn" @click="loginWithApple"> |
|||
<image |
|||
class="apple-icon" |
|||
src="/static/apple-icon.png" |
|||
mode="aspectFit" |
|||
></image> |
|||
<text class="third-party-text">通过 Apple 继续</text> |
|||
</view> |
|||
|
|||
<view class="third-party-btn" @click="loginWithGoogle"> |
|||
<image |
|||
class="google-icon" |
|||
src="/static/google-icon.png" |
|||
mode="aspectFit" |
|||
></image> |
|||
<text class="third-party-text">通过 Google 继续</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 已有账号 --> |
|||
<view class="existing-account"> |
|||
<text class="account-text">已有账号?</text> |
|||
<text class="login-link" @click="goToLogin">登录</text> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref } from 'vue'; |
|||
|
|||
const email = ref(""); |
|||
const phone = ref(""); |
|||
const agreed = ref(false); |
|||
const switchType = ref("Email"); // 默认是邮箱注册 |
|||
const { safeAreaInsets } = uni.getSystemInfoSync() |
|||
|
|||
|
|||
function goBack() { |
|||
// 返回上一页 |
|||
uni.navigateBack(-1); |
|||
} |
|||
|
|||
function switchEmail() { |
|||
// 切换到邮箱注册 |
|||
switchType.value = "Email"; |
|||
} |
|||
|
|||
function switchPhone() { |
|||
// 切换到手机注册 |
|||
switchType.value = "Phone"; |
|||
} |
|||
|
|||
function checkboxClick() { |
|||
agreed.value = !agreed.value; |
|||
} |
|||
|
|||
function openAgreement() { |
|||
// 打开用户协议 |
|||
console.log("打开用户协议"); |
|||
uni.navigateTo({ |
|||
url: "/pages/agreement/agreement", |
|||
}); |
|||
} |
|||
|
|||
function openPrivacy() { |
|||
// 打开隐私政策 |
|||
console.log("打开隐私政策"); |
|||
uni.navigateTo({ |
|||
url: "/pages/privacy/privacy", |
|||
}); |
|||
} |
|||
function register() { |
|||
// 注册逻辑 |
|||
if (switchType.value === "Email" && !email.value) { |
|||
uni.showToast({ |
|||
title: "请输入邮箱地址", |
|||
icon: "none", |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
if (switchType.value === "Phone" && !phone.value) { |
|||
uni.showToast({ |
|||
title: "请输入手机号", |
|||
icon: "none", |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
if (!agreed.value) { |
|||
uni.showToast({ |
|||
title: "请同意用户协议和隐私政策", |
|||
icon: "none", |
|||
}); |
|||
return; |
|||
} |
|||
|
|||
// 发送注册请求 |
|||
if (switchType.value === "Email") { |
|||
console.log("邮箱注册:", email.value); |
|||
} else { |
|||
console.log("手机号注册:", phone.value); |
|||
} |
|||
} |
|||
|
|||
function loginWithApple() { |
|||
// Apple登录逻辑 |
|||
console.log("通过Apple登录"); |
|||
} |
|||
|
|||
function loginWithGoogle() { |
|||
// Google登录逻辑 |
|||
console.log("通过Google登录"); |
|||
} |
|||
|
|||
function goToLogin() { |
|||
// 跳转到登录页 |
|||
uni.navigateTo({ |
|||
url: "/pages/login/login", |
|||
}); |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.login-registration-container { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
padding: 0 40rpx; |
|||
height: 100vh; |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
/* 自定义导航栏样式 */ |
|||
.custom-navbar { |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
/* z-index: 999; */ |
|||
width: 90%; |
|||
height: 80rpx; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 10rpx 40rpx; |
|||
margin-bottom: 20rpx; |
|||
} |
|||
|
|||
.nav-left, |
|||
.nav-right { |
|||
flex: 1; |
|||
} |
|||
|
|||
.nav-right { |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
} |
|||
|
|||
.back-btn, |
|||
.headphone-btn { |
|||
font-size: 36rpx; |
|||
font-weight: bold; |
|||
color: #333333; |
|||
padding: 10rpx; |
|||
} |
|||
|
|||
.logo { |
|||
width: 120rpx; |
|||
height: 120rpx; |
|||
margin-bottom: 60rpx; |
|||
border-radius: 20%; |
|||
} |
|||
|
|||
.welcome-text { |
|||
font-size: 48rpx; |
|||
font-weight: bold; |
|||
color: #333333; |
|||
margin-bottom: 60rpx; |
|||
text-align: left; |
|||
align-self: flex-start; |
|||
} |
|||
.switch-container { |
|||
display: flex; |
|||
margin-bottom: 40rpx; |
|||
align-self: flex-start; |
|||
} |
|||
|
|||
.switch-item { |
|||
font-size: 28rpx; |
|||
color: #999999; |
|||
padding: 10rpx 20rpx; |
|||
position: relative; |
|||
} |
|||
|
|||
.switch-item::after { |
|||
content: ''; |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 50%; |
|||
transform: translateX(-50%); |
|||
width: 60%; /* 控制边框宽度 */ |
|||
height: 2rpx; |
|||
background-color: transparent; |
|||
} |
|||
|
|||
.switch-item.active { |
|||
color: #333333; |
|||
font-weight: 700; |
|||
} |
|||
|
|||
.switch-item.active::after { |
|||
content: ''; |
|||
position: absolute; |
|||
top: 60rpx; |
|||
bottom: 0; |
|||
left: 50%; |
|||
transform: translateX(-50%); |
|||
width: 30%; /* 控制边框宽度 */ |
|||
height: 7rpx; |
|||
background-color: #333333; |
|||
} |
|||
|
|||
.input-container { |
|||
width: 100%; |
|||
margin-bottom: 40rpx; |
|||
} |
|||
|
|||
.input-field { |
|||
width: 90%; |
|||
height: 80rpx; |
|||
border-radius: 20rpx; |
|||
border: 2rpx solid #e5e5e5; |
|||
padding: 0 30rpx; |
|||
font-size: 28rpx; |
|||
color: #333333; |
|||
background-color: #f5f5f5; |
|||
} |
|||
|
|||
.agreement-container { |
|||
/* display: flex; */ |
|||
align-items: center; |
|||
margin-bottom: 40rpx; |
|||
align-self: flex-start; |
|||
} |
|||
|
|||
.checkbox { |
|||
width: 10rpx; |
|||
height: 10rpx; |
|||
margin-right: 30rpx; |
|||
/* flex: content; */ |
|||
} |
|||
|
|||
.agreement-text { |
|||
margin-left: 20rpx; |
|||
font-size: 24rpx; |
|||
color: #666666; |
|||
} |
|||
|
|||
.link { |
|||
color: #333333; |
|||
font-weight: bold; |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
.register-btn { |
|||
width: 100%; |
|||
height: 80rpx; |
|||
background-color: #333333; |
|||
color: white; |
|||
font-size: 32rpx; |
|||
font-weight: bold; |
|||
border-radius: 40rpx; |
|||
margin-bottom: 40rpx; |
|||
} |
|||
|
|||
.or-text { |
|||
font-size: 24rpx; |
|||
color: #999999; |
|||
margin-bottom: 40rpx; |
|||
} |
|||
|
|||
.third-party-login { |
|||
width: 100%; |
|||
margin-bottom: 60rpx; |
|||
} |
|||
.third-party-text { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.third-party-btn { |
|||
width: 100%; |
|||
height: 80rpx; |
|||
background-color: white; |
|||
border: 2rpx solid rgb(249, 249, 249); |
|||
border-radius: 20rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-bottom: 20rpx; |
|||
font-size: 28rpx; |
|||
color: #333333; |
|||
} |
|||
|
|||
.apple-icon { |
|||
width: 30rpx; |
|||
height: 30rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.google-icon { |
|||
width: 30rpx; |
|||
height: 30rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.existing-account { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.account-text { |
|||
font-size: 24rpx; |
|||
color: #666666; |
|||
} |
|||
|
|||
.login-link { |
|||
font-size: 24rpx; |
|||
font-weight: bold; |
|||
color: #333333; |
|||
margin-left: 10rpx; |
|||
text-decoration: underline; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,13 @@ |
|||
<template> |
|||
<view> |
|||
用户协议 |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
|
|||
</script> |
|||
|
|||
<style> |
|||
|
|||
</style> |
|||
@ -0,0 +1,134 @@ |
|||
<template> |
|||
<view class="login-prompt" v-if="showPrompt"> |
|||
<view class="mask" :class="{ 'mask-show': showAnimation }" @click="hide"></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> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, nextTick } from 'vue'; |
|||
|
|||
// 定义响应式数据 |
|||
const showPrompt = ref(false); |
|||
const showAnimation = ref(false); |
|||
|
|||
// 显示弹窗 |
|||
const show = () => { |
|||
showPrompt.value = true; |
|||
// 在下一帧触发动画 |
|||
nextTick(() => { |
|||
setTimeout(() => { |
|||
showAnimation.value = true; |
|||
}, 10); |
|||
}); |
|||
}; |
|||
|
|||
// 隐藏弹窗 |
|||
const hide = () => { |
|||
showAnimation.value = false; |
|||
// 等待动画结束后再隐藏 |
|||
setTimeout(() => { |
|||
showPrompt.value = false; |
|||
}, 300); |
|||
}; |
|||
|
|||
// 跳转到登录页面 |
|||
const goLogin = () => { |
|||
uni.navigateTo({ |
|||
url: '/pages/login/login' |
|||
}); |
|||
hide(); |
|||
}; |
|||
|
|||
// 以访客身份继续 |
|||
const continueAsVisitor = () => { |
|||
// 设置访客模式 |
|||
uni.setStorageSync('visitorMode', true); |
|||
hide(); |
|||
}; |
|||
|
|||
// 暴露方法给外部使用 |
|||
defineExpose({ |
|||
show, |
|||
hide |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.login-prompt { |
|||
position: fixed; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
z-index: 999; |
|||
} |
|||
|
|||
.mask { |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
right: 0; |
|||
bottom: 0; |
|||
background-color: rgba(0, 0, 0, 0.8); |
|||
opacity: 0; |
|||
transition: opacity 0.3s ease; |
|||
} |
|||
|
|||
.mask.mask-show { |
|||
opacity: 1; |
|||
} |
|||
|
|||
.prompt-content { |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
height: 300rpx; |
|||
border-radius: 20rpx 20rpx 0 0; |
|||
background-color: white; |
|||
padding: 20rpx 30rpx; |
|||
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: left; |
|||
font-size: 28rpx; |
|||
font-weight: 700; |
|||
color: #333; |
|||
margin-top: 10rpx; |
|||
margin-bottom: 30rpx; |
|||
} |
|||
|
|||
.login-btn { |
|||
width: 100%; |
|||
height: 80rpx; |
|||
background-color:rgb(35, 84, 230); |
|||
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; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,55 @@ |
|||
<template> |
|||
<view class="content"> |
|||
<image class="logo" src="/static/logo.png"></image> |
|||
<view class="text-area"> |
|||
<text class="title" @click="showLoginPrompt">{{ title }}</text> |
|||
</view> |
|||
<LoginPrompt ref="loginPrompt"></LoginPrompt> |
|||
<button @click="toDeepMate">deepMate</button> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref } from "vue"; |
|||
|
|||
const title = ref("请先登录"); |
|||
const loginPrompt = ref(null); |
|||
|
|||
function showLoginPrompt() { |
|||
loginPrompt.value.show(); |
|||
} |
|||
|
|||
function toDeepMate() { |
|||
uni.navigateTo({ |
|||
url: '/pages/deepMate/deepMate' |
|||
}) |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.content { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.logo { |
|||
height: 200rpx; |
|||
width: 200rpx; |
|||
margin-top: 200rpx; |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
margin-bottom: 50rpx; |
|||
} |
|||
|
|||
.text-area { |
|||
display: flex; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 36rpx; |
|||
color: #8f8f94; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,371 @@ |
|||
<template> |
|||
<view |
|||
class="login-registration-container" |
|||
|
|||
> |
|||
<!-- 自定义导航栏 --> |
|||
<view class="custom-navbar" :style="{ paddingTop: safeAreaInsets?.top + 'px' }"> |
|||
<view class="nav-left"> |
|||
<text class="back-btn" @click="goToIndex"><</text> |
|||
</view> |
|||
<view class="nav-right"> |
|||
<text class="headphone-btn">🎧</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- Logo --> |
|||
<image class="logo" src="/static/logo.png" mode="aspectFit"></image> |
|||
|
|||
<!-- 欢迎语 --> |
|||
<text class="welcome-text">登录</text> |
|||
|
|||
<!-- 邮箱/手机号切换 --> |
|||
<view class="switch-container"> |
|||
<text |
|||
class="switch-item" |
|||
:class="{ active: switchType === 'Email' }" |
|||
@click="switchEmail" |
|||
>邮箱/用户名</text |
|||
> |
|||
<text |
|||
class="switch-item" |
|||
:class="{ active: switchType === 'Phone' }" |
|||
@click="switchPhone" |
|||
>手机号</text |
|||
> |
|||
</view> |
|||
<!-- 输入框 --> |
|||
<view class="input-container"> |
|||
<input |
|||
v-if="switchType === 'Email'" |
|||
class="input-field" |
|||
type="text" |
|||
placeholder="输入邮箱/用户名" |
|||
v-model="email" |
|||
/> |
|||
<input |
|||
v-else |
|||
class="input-field" |
|||
type="text" |
|||
placeholder="输入手机号" |
|||
v-model="phone" |
|||
/> |
|||
</view> |
|||
|
|||
<!-- 用户协议 --> |
|||
<!-- <view class="agreement-container"> |
|||
<checkbox class="checkbox" v-model="agreed" /> |
|||
<text class="agreement-text" |
|||
>接受 <text class="link">用户协议</text> 和 |
|||
<text class="link">隐私政策</text></text |
|||
> |
|||
</view> --> |
|||
|
|||
<!-- 注册按钮 --> |
|||
<button class="register-btn" @click="register">下一步</button> |
|||
|
|||
<!-- 或者 --> |
|||
<text class="or-text">或者</text> |
|||
|
|||
<!-- 第三方登录 --> |
|||
<view class="third-party-login"> |
|||
<view class="third-party-btn" @click="loginWithApple"> |
|||
<image |
|||
class="apple-icon" |
|||
src="/static/apple-icon.png" |
|||
mode="aspectFit" |
|||
></image> |
|||
<text class="third-party-text">通过 Apple 继续</text> |
|||
</view> |
|||
|
|||
<view class="third-party-btn" @click="loginWithGoogle"> |
|||
<image |
|||
class="google-icon" |
|||
src="/static/google-icon.png" |
|||
mode="aspectFit" |
|||
></image> |
|||
<text class="third-party-text">通过 Google 继续</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 已有账号 --> |
|||
<view class="existing-account"> |
|||
<text class="account-text">未注册账号?</text> |
|||
<text class="login-link" @click="goToRegistration">注册</text> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref } from "vue"; |
|||
|
|||
const email = ref(""); |
|||
const phone = ref(""); |
|||
const agreed = ref(false); |
|||
const switchType = ref("Email"); // 默认是邮箱注册 |
|||
const { safeAreaInsets } = uni.getSystemInfoSync(); |
|||
|
|||
function goToIndex() { |
|||
// 返回上一页 |
|||
uni.navigateTo({ url: '/pages/index/index' }); |
|||
} |
|||
|
|||
function switchEmail() { |
|||
// 切换到邮箱注册 |
|||
switchType.value = "Email"; |
|||
} |
|||
|
|||
function switchPhone() { |
|||
// 切换到手机注册 |
|||
switchType.value = "Phone"; |
|||
} |
|||
|
|||
function register() { |
|||
// 注册逻辑 |
|||
if (!email.value) { |
|||
uni.showToast({ |
|||
title: "请输入邮箱地址", |
|||
icon: "none", |
|||
}); |
|||
return; |
|||
} |
|||
if (!agreed.value) { |
|||
uni.showToast({ |
|||
title: "请同意用户协议和隐私政策", |
|||
icon: "none", |
|||
}); |
|||
return; |
|||
} |
|||
// 发送注册请求 |
|||
console.log("注册:", email.value); |
|||
} |
|||
|
|||
function loginWithApple() { |
|||
// Apple登录逻辑 |
|||
console.log("通过Apple登录"); |
|||
} |
|||
|
|||
function loginWithGoogle() { |
|||
// Google登录逻辑 |
|||
console.log("通过Google登录"); |
|||
} |
|||
|
|||
function goToRegistration() { |
|||
// 跳转到登录页 |
|||
uni.navigateTo({ |
|||
url: "/pages/Registration/Registration", |
|||
}); |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.login-registration-container { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
padding: 0 40rpx; |
|||
height: 100vh; |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
/* 自定义导航栏样式 */ |
|||
.custom-navbar { |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
/* z-index: 999; */ |
|||
width: 90%; |
|||
height: 80rpx; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
padding: 10rpx 40rpx; |
|||
margin-bottom: 20rpx; |
|||
} |
|||
|
|||
.nav-left, |
|||
.nav-right { |
|||
flex: 1; |
|||
} |
|||
|
|||
.nav-right { |
|||
display: flex; |
|||
justify-content: flex-end; |
|||
} |
|||
|
|||
.back-btn, |
|||
.headphone-btn { |
|||
font-size: 36rpx; |
|||
font-weight: bold; |
|||
color: #333333; |
|||
padding: 10rpx; |
|||
} |
|||
|
|||
.logo { |
|||
width: 120rpx; |
|||
height: 120rpx; |
|||
margin-bottom: 60rpx; |
|||
border-radius: 20%; |
|||
} |
|||
|
|||
.welcome-text { |
|||
font-size: 48rpx; |
|||
font-weight: bold; |
|||
color: #333333; |
|||
margin-bottom: 60rpx; |
|||
text-align: left; |
|||
align-self: flex-start; |
|||
} |
|||
.switch-container { |
|||
display: flex; |
|||
margin-bottom: 40rpx; |
|||
align-self: flex-start; |
|||
} |
|||
|
|||
.switch-item { |
|||
font-size: 28rpx; |
|||
color: #999999; |
|||
padding: 10rpx 20rpx; |
|||
position: relative; |
|||
} |
|||
|
|||
.switch-item::after { |
|||
content: ""; |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 50%; |
|||
transform: translateX(-50%); |
|||
width: 60%; /* 控制边框宽度 */ |
|||
height: 2rpx; |
|||
background-color: transparent; |
|||
} |
|||
|
|||
.switch-item.active { |
|||
color: #333333; |
|||
font-weight: 700; |
|||
} |
|||
|
|||
.switch-item.active::after { |
|||
content: ""; |
|||
position: absolute; |
|||
top: 60rpx; |
|||
bottom: 0; |
|||
left: 50%; |
|||
transform: translateX(-50%); |
|||
width: 30%; /* 控制边框宽度 */ |
|||
height: 7rpx; |
|||
background-color: #333333; |
|||
} |
|||
|
|||
.input-container { |
|||
width: 100%; |
|||
margin-bottom: 40rpx; |
|||
} |
|||
|
|||
.input-field { |
|||
width: 90%; |
|||
height: 80rpx; |
|||
border-radius: 20rpx; |
|||
border: 2rpx solid #e5e5e5; |
|||
padding: 0 30rpx; |
|||
font-size: 28rpx; |
|||
color: #333333; |
|||
background-color: #f5f5f5; |
|||
} |
|||
|
|||
.agreement-container { |
|||
/* display: flex; */ |
|||
align-items: center; |
|||
margin-bottom: 40rpx; |
|||
align-self: flex-start; |
|||
} |
|||
|
|||
.checkbox { |
|||
width: 10rpx; |
|||
height: 10rpx; |
|||
margin-right: 30rpx; |
|||
/* flex: content; */ |
|||
} |
|||
|
|||
.agreement-text { |
|||
margin-left: 20rpx; |
|||
font-size: 24rpx; |
|||
color: #666666; |
|||
} |
|||
|
|||
.link { |
|||
color: #333333; |
|||
font-weight: bold; |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
.register-btn { |
|||
width: 100%; |
|||
height: 80rpx; |
|||
background-color: #333333; |
|||
color: white; |
|||
font-size: 32rpx; |
|||
font-weight: bold; |
|||
border-radius: 40rpx; |
|||
margin-bottom: 40rpx; |
|||
} |
|||
|
|||
.or-text { |
|||
font-size: 24rpx; |
|||
color: #999999; |
|||
margin-bottom: 40rpx; |
|||
} |
|||
|
|||
.third-party-login { |
|||
width: 100%; |
|||
margin-bottom: 60rpx; |
|||
} |
|||
.third-party-text { |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.third-party-btn { |
|||
width: 100%; |
|||
height: 80rpx; |
|||
background-color: white; |
|||
border: 2rpx solid #e5e5e5; |
|||
border-radius: 40rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-bottom: 20rpx; |
|||
font-size: 28rpx; |
|||
color: #333333; |
|||
} |
|||
|
|||
.apple-icon { |
|||
width: 30rpx; |
|||
height: 30rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.google-icon { |
|||
width: 30rpx; |
|||
height: 30rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.existing-account { |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.account-text { |
|||
font-size: 24rpx; |
|||
color: #666666; |
|||
} |
|||
|
|||
.login-link { |
|||
font-size: 24rpx; |
|||
font-weight: bold; |
|||
color: #333333; |
|||
margin-left: 10rpx; |
|||
text-decoration: underline; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,13 @@ |
|||
<template> |
|||
<view> |
|||
隐私政策 |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
|
|||
</script> |
|||
|
|||
<style> |
|||
|
|||
</style> |
|||
@ -0,0 +1,194 @@ |
|||
<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> |
|||
|
|||
<!-- 底部导航栏 --> |
|||
<!-- <view class="bottom-nav"> |
|||
<navigator url="/pages/index/index" class="nav-item"> |
|||
<image |
|||
class="nav-icon" |
|||
src="/static/images/home.png" |
|||
mode="aspectFill" |
|||
></image> |
|||
<text class="nav-text">首页</text> |
|||
</navigator> |
|||
<navigator url="/pages/index/index" class="nav-item"> |
|||
<image |
|||
class="nav-icon" |
|||
src="/static/images/chart.png" |
|||
mode="aspectFill" |
|||
></image> |
|||
<text class="nav-text">行情</text> |
|||
</navigator> |
|||
<navigator url="/pages/index/index" class="nav-item active"> |
|||
<image |
|||
class="nav-icon" |
|||
src="/static/images/logo.png" |
|||
mode="aspectFill" |
|||
></image> |
|||
<text class="nav-text">DeepMate</text> |
|||
</navigator> |
|||
<navigator url="/pages/index/index" class="nav-item"> |
|||
<image |
|||
class="nav-icon" |
|||
src="/static/images/explore.png" |
|||
mode="aspectFill" |
|||
></image> |
|||
<text class="nav-text">深度探索</text> |
|||
</navigator> |
|||
<navigator url="/pages/index/index" class="nav-item"> |
|||
<image |
|||
class="nav-icon" |
|||
src="/static/images/profile.png" |
|||
mode="aspectFill" |
|||
></image> |
|||
<text class="nav-text">我的</text> |
|||
</navigator> |
|||
</view> --> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
function toRegistration() { |
|||
uni.navigateTo({ |
|||
url: "/pages/Registration/Registration", |
|||
}); |
|||
} |
|||
|
|||
function toLogin() { |
|||
uni.navigateTo({ |
|||
url: "/pages/login/login", |
|||
}); |
|||
} |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.login-container { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
/* justify-content: space-between; */ |
|||
padding: 40rpx; |
|||
height: 100vh; |
|||
background-color: #ffffff; |
|||
} |
|||
|
|||
.title-section { |
|||
text-align: center; |
|||
margin-top: 120rpx; |
|||
|
|||
margin-bottom: 20rpx; |
|||
} |
|||
|
|||
.main-title { |
|||
text-align: center; |
|||
font-size: 64rpx; |
|||
font-weight: 800; |
|||
color: #000000; |
|||
margin-bottom: 10rpx; |
|||
} |
|||
.subtitle-section { |
|||
margin-bottom: 100rpx; |
|||
} |
|||
.subtitle { |
|||
font-weight: bold; |
|||
font-size: 32rpx; |
|||
color: #333333; |
|||
} |
|||
|
|||
.phone-card { |
|||
background-image: url("/static/20251021-132531.jpg"); |
|||
background-size: 100% 100%; |
|||
background-position: center; |
|||
min-width: 400rpx; |
|||
min-height: 700rpx; |
|||
width: 400rpx; |
|||
height: 700rpx; |
|||
border-radius: 40rpx; |
|||
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; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,40 @@ |
|||
<template> |
|||
<view class="background"> |
|||
<view class="logo-text"> DeepChart </view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { onShow } from "@dcloudio/uni-app"; |
|||
|
|||
onShow(() => { |
|||
setTimeout(() => { |
|||
uni.redirectTo({ |
|||
url: "/pages/select/select", |
|||
animationType: "slide-in-right", |
|||
animationDuration: 1000, |
|||
}); |
|||
}, 3000); |
|||
}); |
|||
</script> |
|||
|
|||
<style> |
|||
.background { |
|||
background: linear-gradient(180deg, #2a0c4d, #1d0836, #0d0218); |
|||
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%); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,18 @@ |
|||
// vue.config.js
|
|||
const webpack = require('webpack'); |
|||
|
|||
module.exports = { |
|||
configureWebpack: { |
|||
plugins: [ |
|||
new webpack.DefinePlugin({ |
|||
'__VUE_I18N_FULL_INSTALL__': JSON.stringify(true), |
|||
'__VUE_I18N_LEGACY_API__': JSON.stringify(false), |
|||
'__INTLIFY_PROD_DEVTOOLS__': JSON.stringify(false) |
|||
}) |
|||
] |
|||
}, |
|||
// 如果需要自定义其他 webpack 配置,可以在这里添加
|
|||
chainWebpack: (config) => { |
|||
// 例如,你可以在这里添加其他配置
|
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue