Browse Source

联调选股策略接口

dongqian/feature-20251022181325-deepmate简版
dongqian 4 weeks ago
parent
commit
769382fe25
  1. 9
      api/deepExploration/deepExploration.js
  2. 44
      pages/deepExploration/deepExploration.vue
  3. 318
      pages/deepExploration/stockSelectDetail.vue

9
api/deepExploration/deepExploration.js

@ -92,7 +92,14 @@ export const stocSelectApi = (data) => {
data:data data:data
}) })
} }
//根据名字选股策略
export const stocSelectByNameApi = (data) => {
return http({
method: 'POST',
url: '/api/deep/getStrategyByName',
data:data
})
}
//历史记录详情 //历史记录详情

44
pages/deepExploration/deepExploration.vue

@ -113,7 +113,7 @@
src="/static/deepExploration-images/plus.png" src="/static/deepExploration-images/plus.png"
mode="aspectFill" mode="aspectFill"
></image> ></image>
<text>抄底卖顶</text>
<text>波段行情</text>
</view> </view>
<view class="right"> <view class="right">
<image <image
@ -130,7 +130,7 @@
<view class="contentTitle_price">选股价格</view> <view class="contentTitle_price">选股价格</view>
</view> </view>
<view class="contentItem"> <view class="contentItem">
<view class="row" v-for="(item, index) in stockData" :key="index">
<view class="row" v-for="(item, index) in stockDataByName" :key="index">
<view class="nameItem">{{ item.tscode }}</view> <view class="nameItem">{{ item.tscode }}</view>
<view class="closeItem">{{ item.close }}</view> <view class="closeItem">{{ item.close }}</view>
<view class="priceItem">{{ item.preClose }}</view> <view class="priceItem">{{ item.preClose }}</view>
@ -151,7 +151,7 @@
} from 'vue' } from 'vue'
import footerBar from '@/components/footerBar.vue' import footerBar from '@/components/footerBar.vue'
import deepExploration_header from '@/components/deepExploration_header.vue' import deepExploration_header from '@/components/deepExploration_header.vue'
import { stocSelectApi } from '@/api/deepExploration/deepExploration.js'
import { stocSelectApi, stocSelectByNameApi } from '@/api/deepExploration/deepExploration.js'
const type = ref("deepExploration"); const type = ref("deepExploration");
const iSMT = ref(0); const iSMT = ref(0);
@ -194,6 +194,7 @@ const searchStock = () => {
} }
// //
const stockData = ref([]); const stockData = ref([]);
const stockDataByName = ref([]); //
// //
const loadStockSelection = async () => { const loadStockSelection = async () => {
@ -235,11 +236,48 @@ const searchStock = () => {
} }
} }
//
const loadStockSelectionByName = async () => {
try {
const res = await stocSelectByNameApi({ name: '安徽' })
const raw = res?.data
const dataObj = raw?.data || raw
let list = []
if (Array.isArray(dataObj)) {
list = dataObj
} else if (dataObj && typeof dataObj === 'object') {
const target = dataObj['安徽']
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) {
const mapped = list.map(item => ({
tscode: item.tsCode ?? item.tscode ?? item.code ?? '',
close: item.close ?? item.lastClose ?? '',
preClose: item.preClose ?? item.preclose ?? item.prevClose ?? ''
}))
stockDataByName.value = mapped.slice(0, 3)
console.log('安徽板块列表长度:', stockDataByName.value.length, '首项:', stockDataByName.value[0])
} else {
console.warn('按名称(安徽)接口返回空列表或结构不匹配', raw)
}
} catch (e) {
console.error('按名称(安徽)接口调用失败', e)
uni.showToast({ title: '安徽板块加载失败', icon: 'none' })
}
}
onMounted(() => { onMounted(() => {
// //
iSMT.value = uni.getSystemInfoSync().statusBarHeight; iSMT.value = uni.getSystemInfoSync().statusBarHeight;
// //
loadStockSelection() loadStockSelection()
loadStockSelectionByName() //
}) })
</script> </script>

318
pages/deepExploration/stockSelectDetail.vue

@ -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,176 @@
</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)}%`
}
// ///
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.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.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,6 +252,11 @@
background-color: rgb(243, 243, 243); background-color: rgb(243, 243, 243);
} }
.tabItem-active {
background-color: #DB1F1D; //
color: #fff;
}
} }
} }

Loading…
Cancel
Save