|
|
@ -3,7 +3,7 @@ |
|
|
<view class="table"> |
|
|
<view class="table"> |
|
|
<view class="tableHeader"> |
|
|
<view class="tableHeader"> |
|
|
<scroll-view class="tabs" scroll-x="true"> |
|
|
<scroll-view class="tabs" scroll-x="true"> |
|
|
<view v-for="(item,index) in tabsData" :key="index" class="tabItem" @click="handleTab(item)"> |
|
|
|
|
|
|
|
|
<view v-for="(item,index) in tabsData" :key="index" :class="['tabItem', { 'tabItem-active': item === activeTab }]" @click="handleTab(item)"> |
|
|
{{item}} |
|
|
{{item}} |
|
|
</view> |
|
|
</view> |
|
|
</scroll-view> |
|
|
</scroll-view> |
|
|
@ -23,7 +23,7 @@ |
|
|
</view> |
|
|
</view> |
|
|
</view> |
|
|
</view> |
|
|
<view class="box_content"> |
|
|
<view class="box_content"> |
|
|
<view class="row" v-for="(item,index) in fakeData" :key="index" :class="{ 'increase-positive': item.increase.startsWith('+'), |
|
|
|
|
|
|
|
|
<view class="row" v-for="(item,index) in strategyData" :key="index" :class="{ 'increase-positive': item.increase.startsWith('+'), |
|
|
'increase-negative': item.increase.startsWith('-')}"> |
|
|
'increase-negative': item.increase.startsWith('-')}"> |
|
|
<view class="name_colum"> |
|
|
<view class="name_colum"> |
|
|
<text class="stockName">{{item.name}}</text> |
|
|
<text class="stockName">{{item.name}}</text> |
|
|
@ -48,153 +48,182 @@ |
|
|
</template> |
|
|
</template> |
|
|
|
|
|
|
|
|
<script setup> |
|
|
<script setup> |
|
|
import { |
|
|
|
|
|
ref |
|
|
|
|
|
} from 'vue' |
|
|
|
|
|
|
|
|
|
|
|
const tabsData = ref(['全部', '抄底卖顶', '波段行情', '价值投资', '资金及仓位管理', '价值投资', '价值投资', '价值投资', ]) |
|
|
|
|
|
const handleTab = (item) => { |
|
|
|
|
|
uni.showToast({ |
|
|
|
|
|
title: `查看 ${item} 详情`, |
|
|
|
|
|
icon: 'none', |
|
|
|
|
|
duration: 2000 |
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
import { ref, onMounted } from 'vue' |
|
|
|
|
|
import { stocSelectApi, stocSelectByNameApi } from '@/api/deepExploration/deepExploration.js' |
|
|
|
|
|
import { useUserStore } from '@/stores/modules/userInfo.js' |
|
|
|
|
|
import { useDeviceStore } from '@/stores/modules/deviceInfo.js' |
|
|
|
|
|
import { LoginApi } from '@/api/start/login.js' |
|
|
|
|
|
|
|
|
|
|
|
const tabsData = ref(['全部', '抄底卖顶', '波段行情', '价值投资', '资金及仓位管理', ]) |
|
|
|
|
|
const activeTab = ref('全部') |
|
|
|
|
|
// 点击标签:激活并按需触发名称查询 |
|
|
|
|
|
const handleTab = async (item) => { |
|
|
|
|
|
activeTab.value = item |
|
|
|
|
|
const nameMap = { |
|
|
|
|
|
'抄底卖顶': '北京', |
|
|
|
|
|
'波段行情': '安徽', |
|
|
|
|
|
'价值投资': '重庆', |
|
|
|
|
|
'资金及仓位管理': '黑龙江' |
|
|
|
|
|
} |
|
|
|
|
|
if (item === '全部') { |
|
|
|
|
|
await loadStrategy() |
|
|
|
|
|
uni.showToast({ title: `查看 ${item} 详情`, icon: 'none', duration: 1500 }) |
|
|
|
|
|
return |
|
|
|
|
|
} |
|
|
|
|
|
const apiName = nameMap[item] |
|
|
|
|
|
if (apiName) { |
|
|
|
|
|
await loadByName(apiName) |
|
|
|
|
|
uni.showToast({ title: `${item}数据已更新`, icon: 'none', duration: 1500 }) |
|
|
|
|
|
} else { |
|
|
|
|
|
uni.showToast({ title: `暂不支持:${item}`, icon: 'none' }) |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
//表头是否升序 |
|
|
//表头是否升序 |
|
|
const ifASC = ref(true) |
|
|
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 |
|
|
|
|
|
} |
|
|
|
|
|
]; |
|
|
|
|
|
|
|
|
const tableContentHeaderData = ref(['最新', '涨幅', '涨跌', '昨收', '成交量', '成交额', '开盘价', '最高价', '最低价']) |
|
|
|
|
|
|
|
|
|
|
|
// 渲染用数据 |
|
|
|
|
|
const strategyData = ref([]) |
|
|
|
|
|
|
|
|
|
|
|
// 游客登录兜底,确保移动端有token |
|
|
|
|
|
const ensureAuth = async () => { |
|
|
|
|
|
const userStore = useUserStore() |
|
|
|
|
|
if (userStore.userInfo?.token) return |
|
|
|
|
|
try { |
|
|
|
|
|
const deviceStore = useDeviceStore() |
|
|
|
|
|
let deviceId = deviceStore.deviceInfo?.deviceId |
|
|
|
|
|
if (!deviceId) { |
|
|
|
|
|
const cached = uni.getStorageSync('deviceId') |
|
|
|
|
|
deviceId = cached || `${Date.now()}-${Math.random().toString(36).slice(2, 10)}` |
|
|
|
|
|
uni.setStorageSync('deviceId', deviceId) |
|
|
|
|
|
deviceStore.setDeviceInfo({ ...(deviceStore.deviceInfo || {}), deviceId }) |
|
|
|
|
|
} |
|
|
|
|
|
const res = await LoginApi({ |
|
|
|
|
|
loginType: 'VISITOR', |
|
|
|
|
|
account: deviceId, |
|
|
|
|
|
useCode: false |
|
|
|
|
|
}) |
|
|
|
|
|
if (res?.code === 200 && res?.data?.token) { |
|
|
|
|
|
userStore.setUserInfo(res.data) |
|
|
|
|
|
console.log('游客登录成功,token=', res.data.token) |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn('游客登录失败', res) |
|
|
|
|
|
} |
|
|
|
|
|
} catch (err) { |
|
|
|
|
|
console.warn('游客登录异常', err) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const formatPctChg = (val) => { |
|
|
|
|
|
if (val === null || val === undefined || val === '') return '' |
|
|
|
|
|
const num = Number(val) |
|
|
|
|
|
if (!isFinite(num)) return String(val) |
|
|
|
|
|
const sign = num > 0 ? '+' : '' |
|
|
|
|
|
return `${sign}${num.toFixed(2)}%` |
|
|
|
|
|
} |
|
|
|
|
|
// 默认根据涨幅( pctChg )由大到小排序 |
|
|
|
|
|
const sortByPctDesc = (arr) => arr.sort((a, b) => (Number(b.pctChg) || -Infinity) - (Number(a.pctChg) || -Infinity)) |
|
|
|
|
|
|
|
|
|
|
|
// 按名称加载(抄底卖顶/波段行情/价值投资/资金及仓位管理) |
|
|
|
|
|
const loadByName = async (apiName) => { |
|
|
|
|
|
try { |
|
|
|
|
|
const userStore = useUserStore() |
|
|
|
|
|
if (!userStore.userInfo?.token) { |
|
|
|
|
|
await ensureAuth() |
|
|
|
|
|
} |
|
|
|
|
|
const token = useUserStore().userInfo?.token |
|
|
|
|
|
const res = await stocSelectByNameApi({ name: apiName, token }) |
|
|
|
|
|
const raw = res?.data |
|
|
|
|
|
const dataObj = raw?.data || raw |
|
|
|
|
|
let list = [] |
|
|
|
|
|
if (dataObj && typeof dataObj === 'object' && !Array.isArray(dataObj)) { |
|
|
|
|
|
const target = dataObj[apiName] |
|
|
|
|
|
if (Array.isArray(target)) list = target |
|
|
|
|
|
else { |
|
|
|
|
|
const firstArr = Object.values(dataObj).find(v => Array.isArray(v)) |
|
|
|
|
|
if (Array.isArray(firstArr)) list = firstArr |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if ((!Array.isArray(list) || !list.length) && Array.isArray(raw)) { |
|
|
|
|
|
list = raw |
|
|
|
|
|
} |
|
|
|
|
|
// 排序:涨幅由大到小 |
|
|
|
|
|
if (Array.isArray(list)) list = sortByPctDesc(list) |
|
|
|
|
|
if (Array.isArray(list) && list.length) { |
|
|
|
|
|
strategyData.value = list.map(item => ({ |
|
|
|
|
|
name: item.tsCode ?? item.tscode ?? '', |
|
|
|
|
|
stockCode: item.tsCode ?? item.tscode ?? '', |
|
|
|
|
|
latest: item.close ?? '', |
|
|
|
|
|
increase: formatPctChg(item.pctChg), |
|
|
|
|
|
decrease: item.change ?? '', |
|
|
|
|
|
previousClose: item.preClose ?? item.preclose ?? '', |
|
|
|
|
|
volume: item.vol ?? '', |
|
|
|
|
|
turnover: item.amount ?? '', |
|
|
|
|
|
openingPrice: item.open ?? '', |
|
|
|
|
|
highestPrice: item.high ?? '', |
|
|
|
|
|
lowestPrice: item.low ?? '' |
|
|
|
|
|
})) |
|
|
|
|
|
console.log(`按名称(${apiName})加载成功,条数:`, strategyData.value.length, '首项:', strategyData.value[0]) |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn('getStrategyByName 返回空列表或结构不匹配', raw) |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error('getStrategyByName 接口调用失败', e) |
|
|
|
|
|
uni.showToast({ title: '按名称加载失败', icon: 'none' }) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const loadStrategy = async () => { |
|
|
|
|
|
try { |
|
|
|
|
|
const userStore = useUserStore() |
|
|
|
|
|
if (!userStore.userInfo?.token) { |
|
|
|
|
|
await ensureAuth() |
|
|
|
|
|
} |
|
|
|
|
|
const token = useUserStore().userInfo?.token |
|
|
|
|
|
const res = await stocSelectApi({ language: 'cn', token }) |
|
|
|
|
|
const raw = res?.data |
|
|
|
|
|
const listCandidates = [ |
|
|
|
|
|
raw?.list, |
|
|
|
|
|
raw?.data?.list, |
|
|
|
|
|
raw?.data?.rows, |
|
|
|
|
|
raw?.rows, |
|
|
|
|
|
Array.isArray(raw) ? raw : null |
|
|
|
|
|
].filter(Array.isArray) |
|
|
|
|
|
let list = listCandidates.length ? listCandidates[0] : [] |
|
|
|
|
|
if ((!Array.isArray(list) || !list.length) && raw && typeof raw === 'object' && !Array.isArray(raw)) { |
|
|
|
|
|
const arrays = Object.values(raw).filter(Array.isArray) |
|
|
|
|
|
if (arrays.length) list = arrays.flat() |
|
|
|
|
|
} |
|
|
|
|
|
// 排序:涨幅由大到小 |
|
|
|
|
|
if (Array.isArray(list)) list = sortByPctDesc(list) |
|
|
|
|
|
if (Array.isArray(list) && list.length) { |
|
|
|
|
|
strategyData.value = list.map(item => ({ |
|
|
|
|
|
name: item.tsCode ?? item.tscode ?? '', |
|
|
|
|
|
stockCode: item.tsCode ?? item.tscode ?? '', |
|
|
|
|
|
latest: item.close ?? '', |
|
|
|
|
|
increase: formatPctChg(item.pctChg), |
|
|
|
|
|
decrease: item.change ?? '', |
|
|
|
|
|
previousClose: item.preClose ?? item.preclose ?? '', |
|
|
|
|
|
volume: item.vol ?? '', |
|
|
|
|
|
turnover: item.amount ?? '', |
|
|
|
|
|
openingPrice: item.open ?? '', |
|
|
|
|
|
highestPrice: item.high ?? '', |
|
|
|
|
|
lowestPrice: item.low ?? '' |
|
|
|
|
|
})) |
|
|
|
|
|
console.log('stockSelectDetail 加载成功(已按涨幅降序),条数:', strategyData.value.length, '首项:', strategyData.value[0]) |
|
|
|
|
|
} else { |
|
|
|
|
|
console.warn('stockSelectDetail 接口返回空列表或结构不匹配', raw) |
|
|
|
|
|
} |
|
|
|
|
|
} catch (e) { |
|
|
|
|
|
console.error('stockSelectDetail 接口调用失败', e) |
|
|
|
|
|
uni.showToast({ title: '选股策略详情加载失败', icon: 'none' }) |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
onMounted(() => { |
|
|
|
|
|
loadStrategy() |
|
|
|
|
|
}) |
|
|
</script> |
|
|
</script> |
|
|
|
|
|
|
|
|
<style scoped lang="scss"> |
|
|
<style scoped lang="scss"> |
|
|
@ -229,12 +258,17 @@ |
|
|
background-color: rgb(243, 243, 243); |
|
|
background-color: rgb(243, 243, 243); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.tabItem-active { |
|
|
|
|
|
background-color: #DB1F1D; // 红色 |
|
|
|
|
|
color: #fff; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.tableContent { |
|
|
.tableContent { |
|
|
width: 100%; |
|
|
width: 100%; |
|
|
|
|
|
|
|
|
|
|
|
background-color: #fff; |
|
|
position: relative; |
|
|
position: relative; |
|
|
|
|
|
|
|
|
.showAll { |
|
|
.showAll { |
|
|
|