|
|
@@ -1,17 +1,261 @@
|
|
|
-import { computed } from 'vue'
|
|
|
+import { v4 } from 'uuid'
|
|
|
+import { quoteServerRequest } from '@/services/socket/quote'
|
|
|
import { globalState } from '@/store'
|
|
|
+import moment from 'moment'
|
|
|
+import eventBus from '@/services/bus'
|
|
|
+import socket from '@/services/socket'
|
|
|
|
|
|
-export function useQuote() {
|
|
|
- const quoteList = globalState.getRef('quoteList');
|
|
|
+export default new (class {
|
|
|
+ /** 订阅列表 */
|
|
|
+ private subscribeMap = new Map<string, string[]>();
|
|
|
|
|
|
- const getQuote = (goodscode: string) => {
|
|
|
- const quote = quoteList.value.findIndex((e) => e.goodscode.toUpperCase() === goodscode.toUpperCase());
|
|
|
- if (quote) {
|
|
|
+ constructor() {
|
|
|
+ // 接收行情服务断线重连成功通知
|
|
|
+ eventBus.$on('quoteServerReconnectNotify', () => {
|
|
|
+ this.startSubscribe();
|
|
|
+ })
|
|
|
|
|
|
+ // 接收行情推送通知
|
|
|
+ eventBus.$on('quotePushNotify', (res) => {
|
|
|
+ const tmpList = <Proto.GoodsQuote[]>res;
|
|
|
+
|
|
|
+ tmpList.forEach((item) => {
|
|
|
+ const quoteList = globalState.getRef('quoteList');
|
|
|
+ const quote = quoteList.value.find((e) => e.goodscode.toUpperCase() === item.goodscode?.toUpperCase());
|
|
|
+ const last = item.last ?? 0;
|
|
|
+ const lasttime = (item.date && item.time) ? moment(item.date + item.time, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss') : '';
|
|
|
+
|
|
|
+ if (quote) {
|
|
|
+ // 数据更新
|
|
|
+ let key: keyof Proto.GoodsQuote;
|
|
|
+ for (key in item) {
|
|
|
+ // 只更新有值的属性
|
|
|
+ if (Reflect.has(quote, key)) {
|
|
|
+ type QuoteKey = keyof Ermcp.QuoteDay;
|
|
|
+ type QuoteValue = Ermcp.QuoteDay[QuoteKey];
|
|
|
+ (<QuoteValue>quote[<QuoteKey>key]) = <QuoteValue>(<unknown>item[key]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理最高最低价
|
|
|
+ if (last) {
|
|
|
+ if (last > quote.highest) {
|
|
|
+ quote.highest = last;
|
|
|
+ }
|
|
|
+ if (last < quote.lowest) {
|
|
|
+ quote.lowest = last;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理最新时间
|
|
|
+ if (lasttime) {
|
|
|
+ quote.lasttime = lasttime;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ console.warn('行情推送的商品 ' + item.goodscode + ' 缺少盘面信息')
|
|
|
+ quoteList.value.push({
|
|
|
+ Lastturnover: 0,
|
|
|
+ ask: item.ask ?? 0,
|
|
|
+ ask2: item.ask2 ?? 0,
|
|
|
+ ask3: item.ask3 ?? 0,
|
|
|
+ ask4: item.ask4 ?? 0,
|
|
|
+ ask5: item.ask5 ?? 0,
|
|
|
+ ask6: 0,
|
|
|
+ ask7: 0,
|
|
|
+ ask8: 0,
|
|
|
+ ask9: 0,
|
|
|
+ ask10: 0,
|
|
|
+ askorderid: 0,
|
|
|
+ askorderid2: 0,
|
|
|
+ askorderid3: 0,
|
|
|
+ askorderid4: 0,
|
|
|
+ askorderid5: 0,
|
|
|
+ askordervolume: 0,
|
|
|
+ askordervolume2: 0,
|
|
|
+ askordervolume3: 0,
|
|
|
+ askordervolume4: 0,
|
|
|
+ askordervolume5: 0,
|
|
|
+ askordervolume6: 0,
|
|
|
+ askordervolume7: 0,
|
|
|
+ askordervolume8: 0,
|
|
|
+ askordervolume9: 0,
|
|
|
+ askordervolume10: 0,
|
|
|
+ askqueueinfo: "",
|
|
|
+ askvolume: item.askvolume ?? 0,
|
|
|
+ askvolume2: item.askvolume2 ?? 0,
|
|
|
+ askvolume3: item.askvolume3 ?? 0,
|
|
|
+ askvolume4: item.askvolume4 ?? 0,
|
|
|
+ askvolume5: item.askvolume5 ?? 0,
|
|
|
+ askvolume6: 0,
|
|
|
+ askvolume7: 0,
|
|
|
+ askvolume8: 0,
|
|
|
+ askvolume9: 0,
|
|
|
+ askvolume10: 0,
|
|
|
+ averageprice: 0,
|
|
|
+ bid: item.bid ?? 0,
|
|
|
+ bid2: item.bid2 ?? 0,
|
|
|
+ bid3: item.bid3 ?? 0,
|
|
|
+ bid4: item.bid4 ?? 0,
|
|
|
+ bid5: item.bid5 ?? 0,
|
|
|
+ bid6: 0,
|
|
|
+ bid7: 0,
|
|
|
+ bid8: 0,
|
|
|
+ bid9: 0,
|
|
|
+ bid10: 0,
|
|
|
+ bidorderid: 0,
|
|
|
+ bidorderid2: 0,
|
|
|
+ bidorderid3: 0,
|
|
|
+ bidorderid4: 0,
|
|
|
+ bidorderid5: 0,
|
|
|
+ bidordervolume: 0,
|
|
|
+ bidordervolume2: 0,
|
|
|
+ bidordervolume3: 0,
|
|
|
+ bidordervolume4: 0,
|
|
|
+ bidordervolume5: 0,
|
|
|
+ bidordervolume6: 0,
|
|
|
+ bidordervolume7: 0,
|
|
|
+ bidordervolume8: 0,
|
|
|
+ bidordervolume9: 0,
|
|
|
+ bidordervolume10: 0,
|
|
|
+ bidqueueinfo: "",
|
|
|
+ bidvolume: item.bidvolume ?? 0,
|
|
|
+ bidvolume2: item.bidvolume2 ?? 0,
|
|
|
+ bidvolume3: item.bidvolume3 ?? 0,
|
|
|
+ bidvolume4: item.bidvolume4 ?? 0,
|
|
|
+ bidvolume5: item.bidvolume5 ?? 0,
|
|
|
+ bidvolume6: 0,
|
|
|
+ bidvolume7: 0,
|
|
|
+ bidvolume8: 0,
|
|
|
+ bidvolume9: 0,
|
|
|
+ bidvolume10: 0,
|
|
|
+ calloptionpremiums: item.calloptionpremiums ?? 0,
|
|
|
+ calloptionpremiums2: item.calloptionpremiums2 ?? 0,
|
|
|
+ calloptionpremiums3: item.calloptionpremiums3 ?? 0,
|
|
|
+ calloptionpremiums4: item.calloptionpremiums4 ?? 0,
|
|
|
+ calloptionpremiums5: item.calloptionpremiums5 ?? 0,
|
|
|
+ cleartime: 0,
|
|
|
+ exchangecode: item.exchangecode ?? 0,
|
|
|
+ exchangedate: item.exchangedate ?? 0,
|
|
|
+ goodscode: item.goodscode ?? '',
|
|
|
+ grepmarketprice: 0,
|
|
|
+ highest: item.highest ?? 0,
|
|
|
+ holdincrement: 0,
|
|
|
+ holdvolume: item.holdvolume ?? 0,
|
|
|
+ iep: 0,
|
|
|
+ iev: 0,
|
|
|
+ inventory: item.inventory ?? 0,
|
|
|
+ iscleared: 0,
|
|
|
+ issettled: 0,
|
|
|
+ last,
|
|
|
+ lastlot: 0,
|
|
|
+ lasttime,
|
|
|
+ lastvolume: item.lastvolume ?? 0,
|
|
|
+ limitdown: item.limitlow ?? 0,
|
|
|
+ limitup: item.limithigh ?? 0,
|
|
|
+ lowest: item.lowest ?? 0,
|
|
|
+ nontotalholdervolume: 0,
|
|
|
+ nontotallot: 0,
|
|
|
+ nontotalturnover: 0,
|
|
|
+ nontotalvolume: 0,
|
|
|
+ opened: item.opened ?? 0,
|
|
|
+ opentime: '',
|
|
|
+ orderid: 0,
|
|
|
+ preclose: item.preclose ?? 0,
|
|
|
+ preholdvolume: item.preholdvolume ?? 0,
|
|
|
+ presettle: item.presettle ?? 0,
|
|
|
+ publictradetype: '',
|
|
|
+ putoptionpremiums: item.putoptionpremiums ?? 0,
|
|
|
+ putoptionpremiums2: item.putoptionpremiums2 ?? 0,
|
|
|
+ putoptionpremiums3: item.putoptionpremiums3 ?? 0,
|
|
|
+ putoptionpremiums4: item.putoptionpremiums4 ?? 0,
|
|
|
+ putoptionpremiums5: item.putoptionpremiums5 ?? 0,
|
|
|
+ settle: item.settle ?? 0,
|
|
|
+ strikeprice: 0,
|
|
|
+ totalaskvolume: 0,
|
|
|
+ totalbidvolume: 0,
|
|
|
+ totallot: 0,
|
|
|
+ totalturnover: item.totalturnover ?? 0,
|
|
|
+ totalvolume: item.totalvolume ?? 0,
|
|
|
+ utclasttime: ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开始订阅
|
|
|
+ */
|
|
|
+ startSubscribe() {
|
|
|
+ const subscribeData: Proto.GoodsQuoteReq[] = [];
|
|
|
+
|
|
|
+ this.subscribeMap.forEach((value) => {
|
|
|
+ const item = value.map((code) => ({
|
|
|
+ goodsCode: code,
|
|
|
+ exchangeCode: 250,
|
|
|
+ subState: 0
|
|
|
+ }))
|
|
|
+ subscribeData.push(...item);
|
|
|
+ })
|
|
|
+
|
|
|
+ if (subscribeData.length) {
|
|
|
+ console.log('开始行情订阅', subscribeData)
|
|
|
+ quoteServerRequest({
|
|
|
+ data: subscribeData,
|
|
|
+ success: (res) => {
|
|
|
+ if (res.length) {
|
|
|
+ console.log('行情订阅成功', res)
|
|
|
+ } else {
|
|
|
+ console.error('行情订阅失败')
|
|
|
+ }
|
|
|
+ },
|
|
|
+ fail: (err) => {
|
|
|
+ console.error('行情订阅失败', err)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 没有订阅商品的时候,断开连接
|
|
|
+ socket.closeQuoteServer();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return {
|
|
|
- getQuote
|
|
|
+ /**
|
|
|
+ * 添加订阅
|
|
|
+ * @param goodsCodes
|
|
|
+ * @param key
|
|
|
+ * @returns
|
|
|
+ */
|
|
|
+ addSubscribe(goodsCodes: string[], key?: string) {
|
|
|
+ const uuid = key ?? v4();
|
|
|
+ const value = this.subscribeMap.get(uuid) ?? [];
|
|
|
+
|
|
|
+ // 对相同 key 订阅的商品进行合并处理
|
|
|
+ this.subscribeMap.set(uuid, [...value, ...goodsCodes]);
|
|
|
+ this.startSubscribe();
|
|
|
+
|
|
|
+ return {
|
|
|
+ uuid,
|
|
|
+ stop: () => {
|
|
|
+ console.log('删除订阅', uuid);
|
|
|
+ this.subscribeMap.delete(uuid);
|
|
|
+ this.startSubscribe();
|
|
|
+ },
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除订阅
|
|
|
+ * @param keys
|
|
|
+ */
|
|
|
+ removeSubscribe(...keys: string[]) {
|
|
|
+ if (keys.length) {
|
|
|
+ console.log('删除订阅', keys);
|
|
|
+ keys.forEach((key) => {
|
|
|
+ this.subscribeMap.delete(key);
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.subscribeMap.clear();
|
|
|
+ }
|
|
|
+ this.startSubscribe();
|
|
|
}
|
|
|
-}
|
|
|
+})
|