|
|
@@ -1,10 +1,14 @@
|
|
|
import { shallowRef, reactive, computed, toRefs, onUnmounted } from 'vue'
|
|
|
import { v4 } from 'uuid'
|
|
|
+import { timerTask } from '@/utils/timer'
|
|
|
import { handlePriceColor } from '@/filters'
|
|
|
import { queryMemberGoodsLimitConfig } from '@/services/api/common'
|
|
|
+import { getTodayAccountConfigInfo } from '@/services/api/account'
|
|
|
import { queryErmcpGoods, queryQuoteDay } from '@/services/api/goods'
|
|
|
+import { wordArrayToUint8Array } from '@/services/websocket/package/crypto'
|
|
|
+import { decodeProto } from '@/services/websocket/package/package50/proto'
|
|
|
import { defineStore } from '../store'
|
|
|
-import { timerTask } from '@/utils/timer'
|
|
|
+import CryptoJS from 'crypto-js'
|
|
|
import eventBus from '@/services/bus'
|
|
|
import moment from 'moment'
|
|
|
|
|
|
@@ -21,31 +25,31 @@ export const useFuturesStore = defineStore(() => {
|
|
|
// 请求商品列表成功后的回调集合
|
|
|
// 由于异步请求原因,页面发起行情订阅时商品数据可能还不存在
|
|
|
// 将回调事件收集到合集中,待请求成功后再执行
|
|
|
- const rsponseTask = new Set<() => void>()
|
|
|
+ const dataCompletedCallback = new Set<() => void>()
|
|
|
|
|
|
const state = reactive({
|
|
|
loading: false,
|
|
|
goodsList: <(Model.GoodsRsp & Partial<Model.MemberGoodsLimitConfigRsp>)[]>[], // 商品列表
|
|
|
- goodsQuoteList: <Model.GoodsQuote[]>[], // 商品行情列表
|
|
|
+ quotationList: <Model.GoodsQuote[]>[], // 行情列表
|
|
|
selectedGoodsId: <number | undefined>undefined, // 当前选中的商品ID
|
|
|
})
|
|
|
|
|
|
// 指定市场ID的商品列表
|
|
|
const marketGoodsList = computed(() => {
|
|
|
- const list = state.goodsQuoteList.filter((e) => marketIds.value.includes(e.marketid))
|
|
|
+ const list = state.quotationList.filter((e) => marketIds.value.includes(e.marketid))
|
|
|
return list.sort((a, b) => a.goodscode.localeCompare(b.goodscode)) // 根据 goodscode 字母升序排序
|
|
|
})
|
|
|
|
|
|
// 当前选中的商品
|
|
|
- const selectedGoods = computed(() => state.goodsQuoteList.find((e) => e.goodsid === state.selectedGoodsId))
|
|
|
+ const selectedGoods = computed(() => state.quotationList.find((e) => e.goodsid === state.selectedGoodsId))
|
|
|
|
|
|
- // 请求响应成功后触发
|
|
|
- const onResponse = (callback: () => void) => {
|
|
|
- if (state.goodsQuoteList.length) {
|
|
|
+ // 商品数据加载完成后触发
|
|
|
+ const onDataCompleted = (callback: () => void) => {
|
|
|
+ if (state.quotationList.length) {
|
|
|
setTimeout(() => callback(), 0)
|
|
|
} else {
|
|
|
- rsponseTask.add(callback)
|
|
|
- onUnmounted(() => rsponseTask.delete(callback))
|
|
|
+ dataCompletedCallback.add(callback)
|
|
|
+ onUnmounted(() => dataCompletedCallback.delete(callback))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -64,81 +68,93 @@ export const useFuturesStore = defineStore(() => {
|
|
|
}
|
|
|
|
|
|
const getGoodsListByMarketId = (...marketId: number[]) => {
|
|
|
- const list = state.goodsQuoteList.filter((e) => marketId.includes(e.marketid))
|
|
|
+ const list = state.quotationList.filter((e) => marketId.includes(e.marketid))
|
|
|
return list.sort((a, b) => a.goodscode.localeCompare(b.goodscode)) // 根据 goodscode 字母升序排序
|
|
|
}
|
|
|
|
|
|
const getGoodsListByTradeMode = (...tradeMode: number[]) => {
|
|
|
- const list = state.goodsQuoteList.filter((e) => tradeMode.includes(e.trademode))
|
|
|
+ const list = state.quotationList.filter((e) => tradeMode.includes(e.trademode))
|
|
|
return list.sort((a, b) => a.goodscode.localeCompare(b.goodscode)) // 根据 goodscode 字母升序排序
|
|
|
}
|
|
|
|
|
|
// 获取商品列表
|
|
|
- const getGoodsList = () => {
|
|
|
+ const getGoodsList = async () => {
|
|
|
state.loading = true
|
|
|
state.goodsList = []
|
|
|
- state.goodsQuoteList = []
|
|
|
+ state.quotationList = []
|
|
|
timerTask.clearTimeout('quoteDay')
|
|
|
+
|
|
|
+ // 任务 #5511
|
|
|
+ const { data: accountConfig } = await getTodayAccountConfigInfo()
|
|
|
// 任务 #5197
|
|
|
- queryMemberGoodsLimitConfig({
|
|
|
+ const { data: limitConfig } = await queryMemberGoodsLimitConfig({
|
|
|
data: {
|
|
|
roletype: 7
|
|
|
}
|
|
|
- }).then((cfg) => {
|
|
|
- queryErmcpGoods().then((res) => {
|
|
|
- state.goodsList = res.data.reduce<(Model.GoodsRsp & Partial<Model.MemberGoodsLimitConfigRsp>)[]>((pre, cur) => {
|
|
|
- const item = cfg.data.find((e) => e.goodsid === cur.goodsid)
|
|
|
- // 跳过不显示的商品
|
|
|
- if (item && item.isnodisplay) {
|
|
|
- return pre
|
|
|
- }
|
|
|
- // 组合商品属性
|
|
|
- pre.push({
|
|
|
- ...cur,
|
|
|
- iscannotbuy: item?.iscannotbuy ?? 0,
|
|
|
- iscannotsell: item?.iscannotsell ?? 0
|
|
|
- })
|
|
|
- return pre
|
|
|
- }, [])
|
|
|
-
|
|
|
- const codes = res.data.map((e) => e.goodscode)
|
|
|
- if (codes.length) {
|
|
|
- getQuoteDay(codes)
|
|
|
- }
|
|
|
- })
|
|
|
})
|
|
|
- // 获取商品盘面信息
|
|
|
- const getQuoteDay = (codes: string[]) => {
|
|
|
- queryQuoteDay({
|
|
|
- data: {
|
|
|
- goodsCodes: codes.join(',')
|
|
|
- }
|
|
|
- }).then((res) => {
|
|
|
- // 只遍历有盘面的商品
|
|
|
- // res.data.forEach((item) => {
|
|
|
- // updateGoodsQuote(item)
|
|
|
- // })
|
|
|
- // 遍历所有商品
|
|
|
- codes.forEach((goodscode) => {
|
|
|
- const item = res.data.find((e) => e.goodscode === goodscode)
|
|
|
- updateGoodsQuote(item ?? { goodscode })
|
|
|
- })
|
|
|
- rsponseTask.forEach((fn) => fn())
|
|
|
- rsponseTask.clear()
|
|
|
- }).finally(() => {
|
|
|
- state.loading = false
|
|
|
- if (!state.selectedGoodsId) {
|
|
|
- state.selectedGoodsId = marketGoodsList.value[0]?.goodsid
|
|
|
- }
|
|
|
- // 每5分钟获取一次盘面
|
|
|
- timerTask.setTimeout(() => getQuoteDay(codes), 5 * 60 * 1000, 'quoteDay')
|
|
|
+ const { data: goodsList } = await queryErmcpGoods()
|
|
|
+
|
|
|
+ for (let i = 0; i < goodsList.length; i++) {
|
|
|
+ const item = goodsList[i]
|
|
|
+ const limit = limitConfig.find((e) => e.goodsid === item.goodsid)
|
|
|
+ // 跳过不显示的商品
|
|
|
+ if (limit?.isnodisplay) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ // 更新商品配置
|
|
|
+ const config = accountConfig.todayAccountMargins.find((e) => e.accountid === 0 && e.goodsid === item.goodsid)
|
|
|
+ if (config) {
|
|
|
+ const wordArray = CryptoJS.enc.Base64.parse(config.infocontent) // 解析base64
|
|
|
+ const uint8Array = wordArrayToUint8Array(wordArray)
|
|
|
+ const res = await decodeProto<Proto.MarginInfoStruct>('MarginInfoStruct', uint8Array) // proto数据解析
|
|
|
+ item.marketmarginalgorithm = res.MarginAlgorithm
|
|
|
+ item.marketmarginvalue = res.MarketMarginValue
|
|
|
+ }
|
|
|
+ // 组合商品属性
|
|
|
+ state.goodsList.push({
|
|
|
+ ...item,
|
|
|
+ iscannotbuy: limit?.iscannotbuy ?? 0,
|
|
|
+ iscannotsell: limit?.iscannotsell ?? 0
|
|
|
})
|
|
|
}
|
|
|
+
|
|
|
+ getQuoteDay()
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取商品盘面信息
|
|
|
+ const getQuoteDay = () => {
|
|
|
+ const values = state.goodsList.map((e) => e.goodscode.toString())
|
|
|
+ queryQuoteDay({
|
|
|
+ data: {
|
|
|
+ goodsCodes: values.join(',')
|
|
|
+ }
|
|
|
+ }).then((res) => {
|
|
|
+ // 只遍历有盘面的商品
|
|
|
+ // res.data.forEach((item) => {
|
|
|
+ // updateQuotation(item)
|
|
|
+ // })
|
|
|
+
|
|
|
+ // 遍历所有商品
|
|
|
+ values.forEach((goodscode) => {
|
|
|
+ const item = res.data.find((e) => e.goodscode === goodscode)
|
|
|
+ updateQuotation(item ?? { goodscode })
|
|
|
+ })
|
|
|
+
|
|
|
+ dataCompletedCallback.forEach((callback) => callback())
|
|
|
+ dataCompletedCallback.clear()
|
|
|
+ }).finally(() => {
|
|
|
+ state.loading = false
|
|
|
+ if (!state.selectedGoodsId) {
|
|
|
+ state.selectedGoodsId = marketGoodsList.value[0]?.goodsid
|
|
|
+ }
|
|
|
+ // 每5分钟获取一次盘面
|
|
|
+ timerTask.setTimeout(() => getQuoteDay(), 5 * 60 * 1000, 'quoteDay')
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
// 通过 goodscode 获取实时盘面
|
|
|
const getGoodsQuote = (code: string | number) => {
|
|
|
- return computed(() => state.goodsQuoteList.find((e) => e.goodscode === code || e.goodsid === code))
|
|
|
+ return computed(() => state.quotationList.find((e) => e.goodscode === code || e.goodsid === code))
|
|
|
}
|
|
|
|
|
|
// 通过 goodscode 获取实时行情报价
|
|
|
@@ -204,10 +220,10 @@ export const useFuturesStore = defineStore(() => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 更新商品行情数据
|
|
|
- const updateGoodsQuote = (quote: Partial<Model.QuoteDayRsp>) => {
|
|
|
+ // 更新行情数据
|
|
|
+ const updateQuotation = (quote: Partial<Model.QuoteDayRsp>) => {
|
|
|
// 查找对应的商品行情
|
|
|
- const item: Model.GoodsQuote = state.goodsQuoteList.find((e) => e.goodscode === quote.goodscode) ?? {
|
|
|
+ const item: Model.GoodsQuote = state.quotationList.find((e) => e.goodscode === quote.goodscode) ?? {
|
|
|
goodsid: 0,
|
|
|
goodscode: quote.goodscode ?? '',
|
|
|
goodsname: '',
|
|
|
@@ -319,7 +335,7 @@ export const useFuturesStore = defineStore(() => {
|
|
|
item.iscannotsell = goods.iscannotsell ?? 0
|
|
|
|
|
|
// 向列表添加新数据
|
|
|
- state.goodsQuoteList.push(item)
|
|
|
+ state.quotationList.push(item)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -363,7 +379,7 @@ export const useFuturesStore = defineStore(() => {
|
|
|
}
|
|
|
|
|
|
// 处理行情数据
|
|
|
- const handleQuote = (quote: Proto.Quote): Partial<Model.QuoteDayRsp> => {
|
|
|
+ const handleQuotation = (quote: Proto.Quote): Partial<Model.QuoteDayRsp> => {
|
|
|
const goods = state.goodsList.find((e) => e.goodscode.toUpperCase() === quote.goodscode?.toUpperCase())
|
|
|
// 处理报价小数位
|
|
|
const handleDeimalplace = (value?: number) => {
|
|
|
@@ -430,9 +446,9 @@ export const useFuturesStore = defineStore(() => {
|
|
|
const quotePushNotify = eventBus.$on('QuotePushNotify', (res) => {
|
|
|
const data = res as Proto.Quote[]
|
|
|
data.forEach((item) => {
|
|
|
- const quote = handleQuote(item)
|
|
|
+ const quote = handleQuotation(item)
|
|
|
if (!state.loading) {
|
|
|
- updateGoodsQuote(quote)
|
|
|
+ updateQuotation(quote)
|
|
|
}
|
|
|
// 触发行情监听事件
|
|
|
for (const e of quoteWatchMap.values()) {
|
|
|
@@ -447,7 +463,7 @@ export const useFuturesStore = defineStore(() => {
|
|
|
...toRefs(state),
|
|
|
marketGoodsList,
|
|
|
selectedGoods,
|
|
|
- onResponse,
|
|
|
+ onDataCompleted,
|
|
|
setMarketId,
|
|
|
getQuotePrice,
|
|
|
getGoodsList,
|
|
|
@@ -456,7 +472,7 @@ export const useFuturesStore = defineStore(() => {
|
|
|
getGoodsMarket,
|
|
|
getGoodsListByMarketId,
|
|
|
getGoodsListByTradeMode,
|
|
|
- updateGoodsQuote,
|
|
|
+ updateQuotation,
|
|
|
quoteWatch,
|
|
|
quotePushNotify,
|
|
|
getGoods
|