Browse Source

Merge branch 'milestone-20251031-简版功能开发' of http://39.101.133.168:8807/qimaohong/deepChartVueApp into milestone-20251031-简版功能开发

milestone-20251031-简版功能开发^2
lihuilin 3 weeks ago
parent
commit
2c3e443cc8
  1. 21
      api/customerServicePlatform/customerServicePlatform.js
  2. 13
      components/IndexCard.vue
  3. 1
      components/login-prompt.vue
  4. 122
      pages/customerServicePlatform/questionDetail.vue
  5. 185
      pages/deepExploration/MainForceActions.vue
  6. 6
      pages/deepExploration/deepExploration.vue
  7. 5
      pages/deepExploration/stockSelectDetail.vue
  8. 54
      pages/home/home.vue
  9. 25
      pages/marketSituation/countryMarket.vue
  10. 15
      pages/marketSituation/marketCondition.vue
  11. 30
      pages/marketSituation/marketOverview.vue
  12. 9
      pages/marketSituation/marketSituation.vue
  13. 21
      pages/start/Registration/Registration.vue
  14. 18
      pages/start/login/login.vue
  15. 1341
      pages/start/recoverPassword/list.js
  16. 20
      pages/start/recoverPassword/recoverPassword.vue
  17. 21
      pages/start/startup/startup.vue
  18. BIN
      static/start-gif.gif
  19. 2
      stores/modules/marketSituation.js
  20. 12
      utils/http.js

21
api/customerServicePlatform/customerServicePlatform.js

@ -9,9 +9,24 @@ export const uploadImageApi = (data) => {
data data
}) })
} }
//问题回答
export const getAnswerApi = (data) => {
//问题回答最终内容
export const getAnswerContentApi = (data) => {
return http({
method: 'POST',
url: '/api/customer/getAnswer',
data
})
}
//问题回答轮询
export const getAnswerStatusApi = (data) => {
return http({
method: 'POST',
url: '/api/customer/getState',
data
})
}
//问题回答获取Id
export const getAnswerIdApi = (data) => {
return http({ return http({
method: 'POST', method: 'POST',
url: '/api/customer/askQuestion', url: '/api/customer/askQuestion',

13
components/IndexCard.vue

@ -63,7 +63,18 @@ const props = defineProps({
}); });
const judgeSymbol = (num) => { const judgeSymbol = (num) => {
return num[0] === "-" ? num : "+" + num;
// undefined/null//
if (num === null || num === undefined) return '';
const n = Number(num);
if (!isNaN(n)) {
// '+'
return (n < 0 ? '' : '+') + n;
}
//
const s = String(num).trim();
if (s.startsWith('-')) return s;
if (s.startsWith('+')) return s;
return '+' + s;
}; };
const getMarketFlag = (market) => { const getMarketFlag = (market) => {

1
components/login-prompt.vue

@ -109,6 +109,7 @@ const continueAsVisitor = async () => {
const res = await LoginApi({ const res = await LoginApi({
loginType: "VISITOR", //EMAIL,PHONE,DCCODE,APPLE,GOOGLE,VISITOR loginType: "VISITOR", //EMAIL,PHONE,DCCODE,APPLE,GOOGLE,VISITOR
account: "", // //dccode account: "", // //dccode
phoneCountry: "", //
verifyCode: "", // verifyCode: "", //
password: "", // password: "", //
useCode: "", //使 true/false useCode: "", //使 true/false

122
pages/customerServicePlatform/questionDetail.vue

@ -14,7 +14,7 @@
</view> </view>
</view> </view>
<scroll-view scroll-y class="content-container">
<scroll-view scroll-y class="content-container" :scroll-into-view="scrollIntoView">
<view class="content-header"> <view class="content-header">
<view class="content-header-area"> <view class="content-header-area">
@ -47,7 +47,7 @@
<view class="card-text"> <view class="card-text">
<rich-text :nodes="renderMarkdown(answerContent)"></rich-text> <rich-text :nodes="renderMarkdown(answerContent)"></rich-text>
<view id="answer-end" style="width:1px;height:1px;"></view>
<!-- <text class="card-paragraph"> <!-- <text class="card-paragraph">
{{answerContent}} {{answerContent}}
</text> --> </text> -->
@ -66,7 +66,9 @@
<script> <script>
import { import {
getAnswerApi
getAnswerIdApi,
getAnswerStatusApi,
getAnswerContentApi
} from "../../api/customerServicePlatform/customerServicePlatform"; } from "../../api/customerServicePlatform/customerServicePlatform";
import marked from "marked"; // marked import marked from "marked"; // marked
@ -78,12 +80,21 @@
questionTitle: '', questionTitle: '',
answerContent: '正在思考...', answerContent: '正在思考...',
showLoginRegister: false, showLoginRegister: false,
//
pollInterval: null,
pollTimeout: null,
scrollIntoView: ''
}; };
}, },
mounted() { mounted() {
this.iSMT = uni.getSystemInfoSync().statusBarHeight || 0; this.iSMT = uni.getSystemInfoSync().statusBarHeight || 0;
this.getAnswerContent() this.getAnswerContent()
}, },
onUnload() {
clearInterval(this.pollInterval);
clearTimeout(this.pollTimeout);
clearInterval(this.interval);
},
onLoad(options) { onLoad(options) {
if (options.question) { if (options.question) {
this.questionTitle = decodeURIComponent(options.question); this.questionTitle = decodeURIComponent(options.question);
@ -95,6 +106,18 @@
} }
}, },
methods: { methods: {
scrollToBottom() {
// 使 $nextTick rich-text /DOM
this.$nextTick(() => {
// idscroll-view 使
this.scrollIntoView = 'answer-end';
// 便
setTimeout(() => {
this.scrollIntoView = '';
}, 100);
});
},
renderMarkdown(content) { renderMarkdown(content) {
const renderer = new marked.Renderer(); const renderer = new marked.Renderer();
// renderer.heading = function (text, level) { // renderer.heading = function (text, level) {
@ -120,39 +143,102 @@
}, },
async getAnswerContent() { async getAnswerContent() {
let conversationId = ''; let conversationId = '';
let chatId = '';
//
try { try {
const cache = uni.getStorageSync('conversationId'); const cache = uni.getStorageSync('conversationId');
const chatIdCache = uni.getStorageSync('chatId');
if (cache) conversationId = cache; if (cache) conversationId = cache;
if (chatIdCache) chatId = chatIdCache
} catch (e) { } catch (e) {
conversationId = ''; conversationId = '';
} }
try { try {
const res = await getAnswerApi({
const res = await getAnswerIdApi({
question: this.questionTitle, question: this.questionTitle,
conversationId: conversationId, conversationId: conversationId,
chatId: chatId
}) })
console.log(res) console.log(res)
if (res.code == 200) {
uni.setStorageSync('conversationId', res.data.conversationId);
const answer = res.data.answer
//
let currentIndex = 0;
const answerLength = answer.length;
if (res.code == 200 && res.data.chatId) {
const resConversationId = res.data.conversationId;
const resChatId = res.data.chatId;
uni.setStorageSync('conversationId', resConversationId);
uni.setStorageSync('chatId', resChatId);
let pollCount = 0;
const maxPoll = 10;
this.pollInterval && clearInterval(this.pollInterval);
this.pollTimeout && clearTimeout(this.pollTimeout);
// === ===
const checkStatus = async () => {
pollCount++;
const pollRes = await getAnswerStatusApi({
conversationId: resConversationId,
chatId: resChatId
});
console.log("pollRes =>", pollRes);
const status = pollRes?.data;
//
if (status === "completed") {
clearInterval(this.pollInterval);
clearTimeout(this.pollTimeout);
//
const answerRes = await getAnswerContentApi({
conversationId: resConversationId,
chatId: resChatId
});
console.log("answerRes =>", answerRes);
const answer = answerRes?.data;
//
if (answer) {
//
let currentIndex = 0;
const answerLength = answer.length;
this.interval && clearInterval(this.interval);
this.interval = setInterval(() => {
this.answerContent = answer.slice(0, currentIndex);
currentIndex++;
this.scrollToBottom();
if (currentIndex > answerLength) {
clearInterval(this.interval);
this.scrollToBottom();
}
}, Math.floor(Math.random() * (150 - 30 + 1)) + 30);
} else {
this.answerContent = "获取回答失败,请重试";
}
return;
}
//10
if (pollCount >= maxPoll) {
clearInterval(this.pollInterval);
clearTimeout(this.pollTimeout);
this.answerContent = "获取回答失败,请重试";
return;
}
//
this.interval = setInterval(() => {
this.answerContent = answer.slice(0, currentIndex);
currentIndex++;
};
if (currentIndex > answerLength) {
clearInterval(this.interval);
}
}, Math.floor(Math.random() * (150 - 30 + 1)) + 30);
// 2
this.pollInterval = setInterval(checkStatus, 2000);
// 10s
this.pollTimeout = setTimeout(() => {
clearInterval(this.pollInterval);
this.answerContent = "获取回答失败,请重试";
}, 20000);
} else { } else {
this.answerContent = '获取回答失败,请重试'; this.answerContent = '获取回答失败,请重试';
} }
} catch { } catch {
this.pollInterval && clearInterval(this.pollInterval);
this.pollTimeout && clearTimeout(this.pollTimeout);
this.interval && clearInterval(this.interval);
this.answerContent = '获取回答失败,请重试'; this.answerContent = '获取回答失败,请重试';
} }
}, },

185
pages/deepExploration/MainForceActions.vue

@ -36,12 +36,36 @@
<text>{{stockAdd}}</text> <text>{{stockAdd}}</text>
</view> </view>
<view class="graph_content"> <view class="graph_content">
<view class="charts-box">
<view class="loadingGraph" v-show="graphLoading">加载中...</view>
<view class="charts-box" v-show="!graphLoading">
<!-- uCharts 蜡烛图组件 --> <!-- uCharts 蜡烛图组件 -->
<qiun-data-charts type="candle" :opts="opts" :chartData="chartData" :disableScroll="true" <qiun-data-charts type="candle" :opts="opts" :chartData="chartData" :disableScroll="true"
:ontouch="true" :onzoom="true" :key="chartKey" /> :ontouch="true" :onzoom="true" :key="chartKey" />
</view> </view>
<image src="/static/deepExploration-images/kLineAll.png" mode="aspectFill"></image>
<!-- <image @click.stop="showFullscreenKline" src="/static/deepExploration-images/kLineAll.png"
mode="aspectFill"></image> -->
</view>
</view>
<!-- 全屏横屏弹窗 -->
<view class="fullscreen-mask" v-if="isFullscreen" @click="closeFullscreen">
<view class="fullscreen-container" :style="{ transform: isLandscape ? 'rotate(90deg)' : '' }">
<!-- 关闭按钮 -->
<view class="fullscreen-close" @click.stop="closeFullscreen">
<image src="/static/icons/close.png" mode="widthFix"></image>
</view>
<!-- 横屏切换按钮 -->
<view class="fullscreen-rotate" @click.stop="toggleOrientation">
<image src="/static/icons/rotate.png" mode="widthFix"></image>
</view>
<!-- 全屏K线图 -->
<view class="fullscreen-chart">
<qiun-data-charts type="candle" :opts="fullscreenOpts" :chartData="chartData"
:key="fullscreenChartKey" />
</view>
</view> </view>
</view> </view>
<view class="txt"> <view class="txt">
@ -107,6 +131,39 @@
//ref //ref
const loginPrompt = ref(null) const loginPrompt = ref(null)
//
const isFullscreen = ref(false); //
const isLandscape = ref(true); //
const fullscreenChartKey = ref(0); //
const graphLoading = ref(true)
// K线
const showFullscreenKline = () => {
isFullscreen.value = true;
isLandscape.value = true; //
//
setTimeout(() => {
fullscreenChartKey.value++;
}, 100);
};
//
const closeFullscreen = () => {
isFullscreen.value = false;
};
//
const toggleOrientation = () => {
isLandscape.value = !isLandscape.value;
//
setTimeout(() => {
fullscreenChartKey.value++;
}, 300);
};
// //
const type = ref('deepExploration') const type = ref('deepExploration')
const iSMT = ref(0) const iSMT = ref(0)
@ -159,7 +216,7 @@
const recordId = ref('') const recordId = ref('')
const parentId = ref('') const parentId = ref('')
const stockId = ref('') const stockId = ref('')
const market = ref('')
const market = ref('usa')
const stockTime = ref('2025/10/24') const stockTime = ref('2025/10/24')
const loading = ref(true); const loading = ref(true);
@ -191,7 +248,7 @@
// //
const handleModels = async () => { const handleModels = async () => {
try { try {
graphLoading.value = true
if (userInfo.isVisitor) { if (userInfo.isVisitor) {
console.log('是游客'); console.log('是游客');
loginPrompt.value.show() loginPrompt.value.show()
@ -204,6 +261,7 @@
if (searchName.value == '') { if (searchName.value == '') {
console.log('没有搜索', searchName.value); console.log('没有搜索', searchName.value);
handleDefault() handleDefault()
getServerData()
} else { } else {
if (currentIndex.value == 0) { if (currentIndex.value == 0) {
console.log('搜索', searchName.value); console.log('搜索', searchName.value);
@ -424,6 +482,7 @@
chartData.value = { chartData.value = {
...rawData ...rawData
} }
graphLoading.value = false
chartKey.value++; chartKey.value++;
console.log('chartData', chartData.value); console.log('chartData', chartData.value);
} }
@ -495,6 +554,28 @@
} }
}) })
//
const fullscreenOpts = ref({
...opts.value, //
padding: [30, 30, 30, 30],
xAxis: {
...opts.value.xAxis,
labelCount: 8, //
fontSize: 12
},
yAxis: {
...opts.value.yAxis,
fontSize: 12
},
extra: {
...opts.value.extra,
candle: {
...opts.value.extra.candle,
width: 12 // K线
}
}
});
// 2. K线 // 2. K线
const chartData = ref({ const chartData = ref({
categories: [], categories: [],
@ -548,6 +629,7 @@
let unwatch = null; let unwatch = null;
// onReady // onReady
onMounted(async () => { onMounted(async () => {
iSMT.value = uni.getSystemInfoSync().statusBarHeight iSMT.value = uni.getSystemInfoSync().statusBarHeight
getUserInfo() getUserInfo()
await handleModels() await handleModels()
@ -571,7 +653,8 @@
//k线 //k线
if (historyData.value.stockData.chartData.categories.length > 1) { // if (historyData.value.stockData.chartData.categories.length > 1) { //
historyData.value.stockData.chartData.categories[historyData.value.stockData.chartData.categories.length - 1] = ''; //
historyData.value.stockData.chartData.categories[historyData.value.stockData.chartData
.categories.length - 1] = ''; //
} }
chartData.value = { chartData.value = {
...JSON.parse(JSON.stringify(historyData.value.stockData.chartData)) ...JSON.parse(JSON.stringify(historyData.value.stockData.chartData))
@ -585,7 +668,7 @@
stockChange.value = historyData.value.stockData.StockInformation.Zhang || '5.120%' stockChange.value = historyData.value.stockData.StockInformation.Zhang || '5.120%'
stockAdd.value = historyData.value.stockData.StockInformation.ZhangFu || '22.410' stockAdd.value = historyData.value.stockData.StockInformation.ZhangFu || '22.410'
stockPrice.value = historyData.value.stockData.StockInformation.Price || '435.900' stockPrice.value = historyData.value.stockData.StockInformation.Price || '435.900'
currentIndex.value = historyData.value.model-1
currentIndex.value = historyData.value.model - 1
}, { }, {
deep: true, deep: true,
immediate: true immediate: true
@ -597,7 +680,7 @@
// //
onLoad((e) => { onLoad((e) => {
if (e.index) { if (e.index) {
// currentIndex.value = e.index - 1
currentIndex.value = e.index - 1
console.log('模块:', currentIndex.value) console.log('模块:', currentIndex.value)
} }
if (e.stockName) { if (e.stockName) {
@ -763,15 +846,24 @@
} }
text:nth-child(3) { text:nth-child(3) {
margin-left: 150rpx;
margin-left: 110rpx;
} }
} }
.graph_content { .graph_content {
position: relative; position: relative;
min-height: 500rpx; min-height: 500rpx;
display: flex;
justify-content: center;
align-items: center;
.loadingGraph {
font-size: 35rpx;
color: #6a6a6a;
}
image{
image {
position: absolute; position: absolute;
bottom: 20rpx; bottom: 20rpx;
right: 30rpx; right: 30rpx;
@ -787,6 +879,81 @@
} }
} }
/* 横屏按钮样式 */
.rotate-btn {
background: transparent;
padding: 0 10rpx;
margin-left: 15rpx;
.btn-icon {
width: 36rpx;
height: 36rpx;
vertical-align: middle;
}
}
/* 全屏遮罩 */
.fullscreen-mask {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: #000;
z-index: 9999;
display: flex;
justify-content: center;
align-items: center;
}
/* 全屏容器 */
.fullscreen-container {
width: 100vh;
/* 横屏时宽度等于屏幕高度 */
height: 100vw;
/* 横屏时高度等于屏幕宽度 */
transition: transform 0.3s ease;
position: relative;
}
/* 关闭按钮 */
.fullscreen-close {
position: absolute;
top: 20rpx;
right: 20rpx;
z-index: 10;
image {
width: 48rpx;
height: 48rpx;
}
}
/* 旋转按钮 */
.fullscreen-rotate {
position: absolute;
top: 20rpx;
left: 20rpx;
z-index: 10;
image {
width: 48rpx;
height: 48rpx;
}
}
/* 全屏图表容器 */
.fullscreen-chart {
width: 100%;
height: 100%;
}
/* 竖屏模式适配 */
:deep(.fullscreen-container:not([style*="rotate(90deg)"])) {
width: 100vw;
height: 100vh;
}
.txt { .txt {
background-color: #F3F3F3; background-color: #F3F3F3;
margin-top: 48rpx; margin-top: 48rpx;

6
pages/deepExploration/deepExploration.vue

@ -45,8 +45,8 @@
</view> </view>
</view> </view>
<view class="stockSelection_content">
<view class="selectionItem">
<view class="stockSelection_content" >
<view class="selectionItem" @click="viewAll">
<view class="header"> <view class="header">
<view class="left"> <view class="left">
<image <image
@ -81,7 +81,7 @@
</view> </view>
<view class="stockSelection_content"> <view class="stockSelection_content">
<view class="selectionItem">
<view class="selectionItem" @click="viewAll">
<view class="header"> <view class="header">
<view class="left"> <view class="left">
<image <image

5
pages/deepExploration/stockSelectDetail.vue

@ -342,18 +342,19 @@
display: flex; display: flex;
border-top: 1rpx dashed #eee; border-top: 1rpx dashed #eee;
width: 210%; width: 210%;
font-weight: 400;
&.increase-positive { &.increase-positive {
.other_colum { .other_colum {
color: #2DD357; color: #2DD357;
font-weight: 200;
font-weight: 400;
} }
} }
&.increase-negative { &.increase-negative {
.other_colum { .other_colum {
color: #FF4150; color: #FF4150;
font-weight: 200;
font-weight: 400;
} }
} }

54
pages/home/home.vue

@ -113,7 +113,7 @@
</view> </view>
</view> </view>
<view class="stock-chart"> <view class="stock-chart">
<image :src="item.chartImg || '/static/c5.png'" mode="aspectFit" class="chart-image"></image>
<image :src="getChartImage(item)" mode="aspectFit" class="chart-image"></image>
</view> </view>
</view> </view>
</view> </view>
@ -232,9 +232,9 @@ export default {
// //
myStocks: [ myStocks: [
{ name: '特斯拉', code: 'TSLA', price: '482.00', change: 2.80, chartImg: '/static/c5.png' },
{ name: '英伟达', code: 'NVDA', price: '189.800', change: -2.92, chartImg: '/static/c6.png' },
{ name: '苹果', code: 'AAPL', price: '256.430', change: 2.60, chartImg: '/static/c7.png' }
{ name: '特斯拉', code: 'TSLA', price: '482.00', change: 2.80 },
{ name: '英伟达', code: 'NVDA', price: '189.800', change: -2.92 },
{ name: '苹果', code: 'AAPL', price: '256.430', change: 2.60 }
], ],
// //
@ -344,15 +344,17 @@ export default {
// //
this.myStocks.forEach(stock => { this.myStocks.forEach(stock => {
// 使getChartImage
const imageSrc = this.getChartImage(stock);
// 使uni.getImageInfoImage // 使uni.getImageInfoImage
uni.getImageInfo({ uni.getImageInfo({
src: stock.chartImg,
src: imageSrc,
success: function(res) { success: function(res) {
// //
console.log('图片预加载成功:', stock.name)
console.log('图片预加载成功:', stock.name, imageSrc)
}, },
fail: function(err) { fail: function(err) {
console.log('图片预加载失败:', err)
console.log('图片预加载失败:', err, imageSrc)
} }
}) })
}) })
@ -433,6 +435,26 @@ export default {
}, },
methods: { methods: {
//
getChartImage(item) {
//
const changeValue = item.change_percent || item.change || item.change_amount || 0;
// 使
if (item.chartImg) {
return item.chartImg;
}
//
if (parseFloat(changeValue) >= 0) {
// 使
return '/static/marketSituation-image/upTimeChart.png';
} else if (parseFloat(changeValue) < 0) {
// 使
return '/static/marketSituation-image/downTimeChart.png';
}
},
// //
goToCustomerService() { goToCustomerService() {
uni.navigateTo({ uni.navigateTo({
@ -650,9 +672,11 @@ export default {
this.myStocks = stockData.map(stock => ({ this.myStocks = stockData.map(stock => ({
name: stock.name || stock.stock_name || '', name: stock.name || stock.stock_name || '',
code: stock.code || stock.stock_code || '', code: stock.code || stock.stock_code || '',
// price: stock.price || stock.current_price || '0.00',
// change: stock.change || stock.change_percent || 0,
chartImg: stock.chartImg || '/static/c5.png' //
price: stock.price || stock.current_price || '0.00',
change: stock.change || stock.change_percent || 0,
change_percent: stock.change_percent || 0,
change_amount: stock.change_amount || 0
// chartImggetChartImage
})) }))
// //
this.institutionalReports = stockData.map(stock => ({ this.institutionalReports = stockData.map(stock => ({
@ -665,13 +689,15 @@ export default {
this.myStocks = stockData.list.map(stock => ({ this.myStocks = stockData.list.map(stock => ({
name: stock.name || stock.stock_name || '', name: stock.name || stock.stock_name || '',
code: stock.code || stock.stock_code || '', code: stock.code || stock.stock_code || '',
// price: stock.price || stock.current_price || '0.00',
// change: stock.change || stock.change_percent || 0,
chartImg: stock.chartImg || '/static/c5.png' //
price: stock.price || stock.current_price || '0.00',
change: stock.change || stock.change_percent || 0,
change_percent: stock.change_percent || 0,
change_amount: stock.change_amount || 0
// chartImggetChartImage
})) }))
// //
// //
this.institutionalReports = stockData.map(stock => ({
this.institutionalReports = stockData.list.map(stock => ({
stock: stock.name || stock.stock_name || '', stock: stock.name || stock.stock_name || '',
status: stock.code || stock.stock_code || '', status: stock.code || stock.stock_code || '',
})) }))

25
pages/marketSituation/countryMarket.vue

@ -17,7 +17,7 @@
</view> </view>
<view class="indices_grid"> <view class="indices_grid">
<view v-for="(index, i) in countryInfo" :key="i" class="index_item"> <view v-for="(index, i) in countryInfo" :key="i" class="index_item">
<IndexCard :market="index.market" :stockName="index.name" :currentPrice="index.price" :changeAmount="index.change" :changePercent="index.changePercent" :isRising="index.isRising" />
<IndexCard :market="index.market" :stockName="index.name" :currentPrice="index.price" :changeAmount="index.change" :changePercent="index.changePercent" :isRising="index.isRising" @click="viewIndexDetail(index,i)"/>
</view> </view>
</view> </view>
@ -95,6 +95,8 @@
import { ref, computed, onMounted, watch } from "vue"; import { ref, computed, onMounted, watch } from "vue";
import IndexCard from "../../components/IndexCard.vue"; import IndexCard from "../../components/IndexCard.vue";
import { queryStockDataAPI } from "@/api/marketSituation/marketSituation"; import { queryStockDataAPI } from "@/api/marketSituation/marketSituation";
import { useMarketSituationStore } from "../../stores/modules/marketSituation.js";
const marketSituationStore = useMarketSituationStore();
onMounted(() => { onMounted(() => {
switchTab(0); switchTab(0);
@ -111,6 +113,11 @@ const switchTab = (i) => {
}).then((res) => { }).then((res) => {
if (res.code === 200) { if (res.code === 200) {
countryInfo.value = res.data.dataPage.records; countryInfo.value = res.data.dataPage.records;
marketSituationStore.countryMarketCardData = countryInfo.value.map((item) => ({
market: item.market,
stockCode: item.code,
stockName: item.name,
}));
console.log(res.data) console.log(res.data)
console.log(res.data.dataPage.records) console.log(res.data.dataPage.records)
console.log(countryInfo.value); console.log(countryInfo.value);
@ -149,12 +156,23 @@ const props = defineProps({
// //
const countryInfo = ref('') const countryInfo = ref('')
//
const viewIndexDetail = (item, index) => {
console.log("查看指数详情:", item);
uni.navigateTo({
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}&index=${index}&from=countryMarket`,
});
};
// //
const handleTabData = (tabData) => { const handleTabData = (tabData) => {
if (tabData && tabData.type === 'country' && tabData.data) { if (tabData && tabData.type === 'country' && tabData.data) {
if (tabData.data.dataPage && tabData.data.dataPage.records) { if (tabData.data.dataPage && tabData.data.dataPage.records) {
countryInfo.value = tabData.data.dataPage.records; countryInfo.value = tabData.data.dataPage.records;
marketSituationStore.countryMarketCardData = countryInfo.value.map((item) => ({
market: item.market,
stockCode: item.code,
stockName: item.name,
}));
console.log('countryMarket接收到数据:', countryInfo.value); console.log('countryMarket接收到数据:', countryInfo.value);
} }
} }
@ -169,9 +187,6 @@ watch(() => props.tabData, (newTabData) => {
// //
const viewMore = (type) => { const viewMore = (type) => {
// type
// indices/sectors/stocks
// uni.navigateTo({ url: `/pages/marketSituation/${type}List` })
}; };
</script> </script>

15
pages/marketSituation/marketCondition.vue

@ -660,6 +660,8 @@ const toLeftPage = () => {
nextStockInformation = marketSituationStore.marketDetailCardData[currentStockIndex.value]; nextStockInformation = marketSituationStore.marketDetailCardData[currentStockIndex.value];
} else if (currentStockFrom.value == "globalIndex") { } else if (currentStockFrom.value == "globalIndex") {
nextStockInformation = marketSituationStore.gloablCardData[currentStockParentIndex.value].list[currentStockIndex.value]; nextStockInformation = marketSituationStore.gloablCardData[currentStockParentIndex.value].list[currentStockIndex.value];
} else if (currentStockFrom.value == "countryMarket") {
nextStockInformation = marketSituationStore.countryMarketCardData[currentStockIndex.value];
} else { } else {
uni.showToast({ uni.showToast({
title: "没有更多股票了", title: "没有更多股票了",
@ -713,6 +715,19 @@ const toRightPage = () => {
nextStockInformation = marketSituationStore.gloablCardData[currentStockParentIndex.value].list[currentStockIndex.value]; nextStockInformation = marketSituationStore.gloablCardData[currentStockParentIndex.value].list[currentStockIndex.value];
updateStockInformation(nextStockInformation); updateStockInformation(nextStockInformation);
} }
} else if (currentStockFrom.value == "countryMarket") {
if (currentStockIndex.value == marketSituationStore.countryMarketCardData.length) {
uni.showToast({
title: "没有更多股票了",
icon: "none",
duration: 1000,
});
return;
} else {
currentStockIndex.value++;
nextStockInformation = marketSituationStore.countryMarketCardData[currentStockIndex.value];
updateStockInformation(nextStockInformation);
}
} else { } else {
uni.showToast({ uni.showToast({
title: "没有更多股票了", title: "没有更多股票了",

30
pages/marketSituation/marketOverview.vue

@ -8,16 +8,16 @@
<view class="content"> <view class="content">
<view class="map"> <view class="map">
<view class="INDU" <view class="INDU"
>道琼斯<view :class="getSignClass(INDU.value)">{{ judgeSymbol(INDU.value) }}</view></view
>道琼斯<view :class="getSignClass(INDU.value)" @click="viewDetail(INDU)">{{ judgeSymbol(INDU.value) }}</view></view
> >
<view class="NDX" <view class="NDX"
>纳斯达克<view :class="getSignClass(NDX.value)">{{ judgeSymbol(NDX.value) }}</view></view
>纳斯达克<view :class="getSignClass(NDX.value)" @click="viewDetail(NDX)">{{ judgeSymbol(NDX.value) }}</view></view
> >
<view class="HSI" <view class="HSI"
>恒生指数<view :class="getSignClass(HSI.value)">{{ judgeSymbol(HSI.value) }}</view></view
>恒生指数<view :class="getSignClass(HSI.value)" @click="viewDetail(HSI)">{{ judgeSymbol(HSI.value) }}</view></view
> >
<view class="CN" <view class="CN"
>上证指数<view :class="getSignClass(CN.value)">{{ judgeSymbol(CN.value) }}</view></view
>上证指数<view :class="getSignClass(CN.value)" @click="viewDetail(CN)">{{ judgeSymbol(CN.value) }}</view></view
> >
<image src="/static/marketSituation-image/map.png" mode="widthFix"></image> <image src="/static/marketSituation-image/map.png" mode="widthFix"></image>
</view> </view>
@ -83,6 +83,12 @@ const CN = ref({ stockName: "上证指数", stockCode: "1A0001", value: "" });
const pageIndex = ref(0); const pageIndex = ref(0);
const scrollToView = ref(""); const scrollToView = ref("");
const viewDetail = (item) => {
uni.navigateTo({
url: `/pages/marketSituation/marketCondition?stockInformation=${encodeURIComponent(JSON.stringify(item))}&from=map`,
});
};
// contenttop // contenttop
const contentTopPosition = computed(() => { const contentTopPosition = computed(() => {
const statusBarHeight = iSMT.value || 0; const statusBarHeight = iSMT.value || 0;
@ -800,8 +806,8 @@ watch(headerHeight, (newHeight) => {
.NDX { .NDX {
position: absolute; position: absolute;
top: 30%;
left: 17%;
top: 23vh;
left: 17vw;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
font-size: 11rpx; font-size: 11rpx;
color: #000000; color: #000000;
@ -815,8 +821,8 @@ watch(headerHeight, (newHeight) => {
} }
.INDU { .INDU {
position: absolute; position: absolute;
top: 22%;
left: 35%;
top: 15vh;
left: 35vw;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
font-size: 11rpx; font-size: 11rpx;
color: #000000; color: #000000;
@ -830,8 +836,8 @@ watch(headerHeight, (newHeight) => {
} }
.HSI { .HSI {
position: absolute; position: absolute;
top: 30%;
right: 4%;
top: 23vh;
right: 4vw;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
font-size: 11rpx; font-size: 11rpx;
color: #000000; color: #000000;
@ -845,8 +851,8 @@ watch(headerHeight, (newHeight) => {
} }
.CN { .CN {
position: absolute; position: absolute;
top: 23%;
right: 8%;
top: 16vh;
right: 8vw;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
font-size: 11rpx; font-size: 11rpx;
color: #000000; color: #000000;

9
pages/marketSituation/marketSituation.vue

@ -177,11 +177,10 @@ const selected = () => {
// //
const history = () => { const history = () => {
uni.showToast({
title: "历史记录",
icon: "none",
});
//
//
uni.navigateTo({
url: '/pages/customStockList/customStockList'
})
}; };
// Tab // Tab

21
pages/start/Registration/Registration.vue

@ -189,7 +189,7 @@
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
// //
import countryList from "../login/list";
import countryList from "../Registration/list";
import footerBar from "../../../components/footerBar"; import footerBar from "../../../components/footerBar";
import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue"; import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
import { verificationPhone, verificationEmail } from "../login/verification"; import { verificationPhone, verificationEmail } from "../login/verification";
@ -198,12 +198,13 @@ import {
SendEmailCodeApi, SendEmailCodeApi,
SendPhoneCodeApi, SendPhoneCodeApi,
} from "../../../api/start/login"; } from "../../../api/start/login";
import { useDeviceStore} from "../../../stores/modules/deviceInfo"
import { useUserStore} from "../../../stores/modules/userInfo"
import { useDeviceStore } from "../../../stores/modules/deviceInfo";
import { useUserStore } from "../../../stores/modules/userInfo";
const type = ref(""); const type = ref("");
const email = ref(""); const email = ref("");
const password = ref(""); const password = ref("");
const deepChartID = ref("");
const phone = ref(""); const phone = ref("");
const country = ref("+86"); const country = ref("+86");
const agreed = ref(false); const agreed = ref(false);
@ -241,6 +242,7 @@ function showCountryPicker() {
), ),
success: function (res) { success: function (res) {
selectedCountry.value = countries.value[res.tapIndex]; selectedCountry.value = countries.value[res.tapIndex];
country.value = selectedCountry.value.code;
}, },
}); });
} }
@ -253,7 +255,7 @@ function goToIndex() {
} }
function goToService() { function goToService() {
//
//
uni.navigateTo({ uni.navigateTo({
url: "/pages/customerServicePlatform/csPlatformIndex", url: "/pages/customerServicePlatform/csPlatformIndex",
}); });
@ -281,14 +283,15 @@ async function register() {
const registerType = changeLoginType(); const registerType = changeLoginType();
isLoading.value = true; isLoading.value = true;
const deviceStore = useDeviceStore()
const deviceStore = useDeviceStore();
const res = await registerApi({ const res = await registerApi({
registerType: registerType, registerType: registerType,
phoneCountry: country.value, //
account: account, account: account,
verifyCode: verifyCode.value, verifyCode: verifyCode.value,
agree: agreed.value, agree: agreed.value,
deviceId:deviceStore.deviceInfo.deviceId
deviceId: deviceStore.deviceInfo.deviceId,
}); });
isLoading.value = false; isLoading.value = false;
@ -326,7 +329,7 @@ function changeAccount() {
} }
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
account.value = `${country.value}-${phone.value}`;
account.value = phone.value;
} }
if (switchType.value === "Email") { if (switchType.value === "Email") {
account.value = email.value; account.value = email.value;
@ -511,9 +514,9 @@ async function sendCode() {
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
// //
const phoneAll = `${country.value}-${phone.value}`;
const res = await SendPhoneCodeApi({ const res = await SendPhoneCodeApi({
phone: phoneAll,
phoneCountry: country.value, //
phone: phone.value,
}); });
console.log("手机验证码:", res.message); console.log("手机验证码:", res.message);

18
pages/start/login/login.vue

@ -377,6 +377,7 @@ async function Login() {
isLoading.value = true; isLoading.value = true;
const res = await LoginApi({ const res = await LoginApi({
loginType: loginType, loginType: loginType,
phoneCountry: country.value, //
account: account, account: account,
verifyCode: verifyCode.value, verifyCode: verifyCode.value,
password: password.value, password: password.value,
@ -430,6 +431,15 @@ function basicVerification() {
}); });
return false; return false;
} }
if (password.value.length < 8) {
uni.showToast({
title: "密码长度不能少于8位",
icon: "none",
});
return false;
}
} }
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
@ -442,8 +452,6 @@ function basicVerification() {
return false; return false;
} }
const phoneAll = `${country.value}${phone.value}`;
console.log("完整手机号" + phoneAll);
if (!validatePhoneNumber(country.value, phone.value)) { if (!validatePhoneNumber(country.value, phone.value)) {
return false; return false;
} }
@ -551,7 +559,7 @@ function changeAccount() {
} }
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
account.value = `${country.value}-${phone.value}`;
account.value = phone.value;
} }
if (switchType.value === "Email") { if (switchType.value === "Email") {
account.value = email.value; account.value = email.value;
@ -667,9 +675,9 @@ async function sendCode() {
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
// //
const phoneAll = `${country.value}-${phone.value}`;
const res = await SendPhoneCodeApi({ const res = await SendPhoneCodeApi({
phone: phoneAll,
phoneCountry: country.value, //
phone: phone.value,
}); });
console.log("手机验证码:", res.message); console.log("手机验证码:", res.message);

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

20
pages/start/recoverPassword/recoverPassword.vue

@ -232,7 +232,7 @@
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
// //
import countryList from "../login/list";
import countryList from "../recoverPassword/list";
import footerBar from "../../../components/footerBar"; import footerBar from "../../../components/footerBar";
import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue"; import uniPopup from "../../../uni_modules/uni-popup/components/uni-popup/uni-popup.vue";
import { verificationPhone, verificationEmail } from "../login/verification"; import { verificationPhone, verificationEmail } from "../login/verification";
@ -248,6 +248,7 @@ const email = ref("");
const password = ref(""); const password = ref("");
const newPasswordFirst = ref(""); const newPasswordFirst = ref("");
const newPasswordSecond = ref(""); const newPasswordSecond = ref("");
const deepChartID = ref("");
const phone = ref(""); const phone = ref("");
const country = ref("+86"); const country = ref("+86");
const agreed = ref(false); const agreed = ref(false);
@ -287,6 +288,7 @@ function showCountryPicker() {
), ),
success: function (res) { success: function (res) {
selectedCountry.value = countries.value[res.tapIndex]; selectedCountry.value = countries.value[res.tapIndex];
country.value = selectedCountry.value.code;
}, },
}); });
} }
@ -333,6 +335,14 @@ async function register() {
return; return;
} }
if (newPasswordFirst.value.length < 8) {
uni.showToast({
title: "密码长度不能少于8位",
icon: "none",
});
return false;
}
const account = changeAccount(); const account = changeAccount();
const res = await forgetApi({ const res = await forgetApi({
@ -429,6 +439,7 @@ async function register() {
const res = await verifyCodeApi({ const res = await verifyCodeApi({
loginType: loginType, //EMAIL,PHONE loginType: loginType, //EMAIL,PHONE
phoneCountry: country.value, //
account: account, // / account: account, // /
verifyCode: verifyCode.value, verifyCode: verifyCode.value,
}); });
@ -451,7 +462,7 @@ function changeAccount() {
} }
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
account.value = `${country.value}-${phone.value}`;
account.value = phone.value;
} }
if (switchType.value === "Email") { if (switchType.value === "Email") {
account.value = email.value; account.value = email.value;
@ -570,10 +581,9 @@ function sendCode() {
} }
} }
if (switchType.value === "Phone") { if (switchType.value === "Phone") {
const phoneAll = `${country.value}-${phone.value}`;
const res = SendPhoneCodeApi({ const res = SendPhoneCodeApi({
phone: phoneAll,
phoneCountry: country.value, //
phone: phone.value,
}); });
if (!res) { if (!res) {
uni.showToast({ uni.showToast({

21
pages/start/startup/startup.vue

@ -1,13 +1,17 @@
<template> <template>
<view class="background"> <view class="background">
<!-- <image
<!-- <image
class="logo" class="logo"
src="../../../static/icons/start-logo.png" src="../../../static/icons/start-logo.png"
mode="scaleToFill" mode="scaleToFill"
/> />
<view class="logo-text"> DeepChart </view> --> <view class="logo-text"> DeepChart </view> -->
<image class="start" src="../../../static/start.webp" mode="scaleToFill" />
<image
class="start"
src="../../../static/start-gif.gif"
mode="scaleToFill"
/>
</view> </view>
</template> </template>
@ -40,20 +44,23 @@ onShow(() => {
animationDuration: 1000, animationDuration: 1000,
}); });
} }
}, 3000);
}, 3400);
}); });
</script> </script>
<style> <style>
.background { .background {
background: linear-gradient(180deg, #fb6967, #fb6967);
background: #ffffff;
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
display: flex;
justify-content: center;
align-items: center;
} }
.start{
width: 100vw;
height: 100vh;
.start {
width: 750rpx;
height: 1624rpx;
} }
.logo-text { .logo-text {

BIN
static/start-gif.gif

After

Width: 750  |  Height: 1624  |  Size: 414 KiB

2
stores/modules/marketSituation.js

@ -9,11 +9,13 @@ export const useMarketSituationStore = defineStore(
const cardData = ref([]); const cardData = ref([]);
const gloablCardData = ref([]); const gloablCardData = ref([]);
const marketDetailCardData = ref([]); const marketDetailCardData = ref([]);
const countryMarketCardData = ref([]);
// 记得 return // 记得 return
return { return {
cardData, cardData,
gloablCardData, gloablCardData,
marketDetailCardData, marketDetailCardData,
countryMarketCardData,
}; };
}, },
// TODO: 持久化 // TODO: 持久化

12
utils/http.js

@ -77,18 +77,20 @@ export const http = (options) => {
} }
if (result.data.code === 400) {
if (result.data.code === 10003) {
const userStore = useUserStore() const userStore = useUserStore()
userStore.clearUserInfo()
uni.showModal({ uni.showModal({
title: "登录失效", title: "登录失效",
content: "点击确定跳转登录页面", content: "点击确定跳转登录页面",
confirmText: "确定", confirmText: "确定",
cancelText: "取消", cancelText: "取消",
success: (res) => { success: (res) => {
uni.navigateTo({
url: '/pages/start/login/login'
})
if (res.confirm) {
userStore.clearUserInfo()
uni.navigateTo({
url: '/pages/start/login/login'
})
}
}, },
}); });
} }

Loading…
Cancel
Save