处理做市商列表
This commit is contained in:
parent
d2b51ffe5f
commit
38d2cf7532
|
|
@ -26,15 +26,16 @@ interface PositionObj {
|
||||||
export const useOrderPositionStore = defineStore('orderPosition', () => {
|
export const useOrderPositionStore = defineStore('orderPosition', () => {
|
||||||
const positionOrderList = ref<PositionObj[]>([])
|
const positionOrderList = ref<PositionObj[]>([])
|
||||||
|
|
||||||
const handleInfoListData = (positionObj: PositionObj) => {
|
const handleInfoListData = (list: PositionObj[]) => {
|
||||||
if (positionObj?.orderNo) {
|
if (list?.length) {
|
||||||
const existingIndex = positionOrderList.value.findIndex(
|
for (let i = 0; i < list.length; i++) {
|
||||||
(p: PositionObj) => p.orderNo === positionObj.orderNo,
|
const idx = positionOrderList.value.findIndex((item)=>item.id === list[i]?.id)
|
||||||
)
|
if (idx !== -1) {
|
||||||
if (existingIndex !== -1) {
|
positionOrderList.value.splice(idx, 1, list[i] as PositionObj)
|
||||||
positionOrderList.value[existingIndex] = positionObj
|
}else{
|
||||||
} else {
|
positionOrderList.value.push(list[i] as PositionObj)
|
||||||
positionOrderList.value.unshift(positionObj)
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,6 +46,7 @@ export const useOrderPositionStore = defineStore('orderPosition', () => {
|
||||||
|
|
||||||
const handlePositionOrderList = async (item:string) => {
|
const handlePositionOrderList = async (item:string) => {
|
||||||
const fields = item.split(':')
|
const fields = item.split(':')
|
||||||
|
console.log(fields)
|
||||||
const positionObj: PositionObj = {
|
const positionObj: PositionObj = {
|
||||||
id: fields[2], // 订单号
|
id: fields[2], // 订单号
|
||||||
account: fields[0], // 账户id
|
account: fields[0], // 账户id
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ export const useTransactionStore = defineStore('transaction', () => {
|
||||||
*/
|
*/
|
||||||
const initMarketConditionsMQTT = async (): Promise<void> => {
|
const initMarketConditionsMQTT = async (): Promise<void> => {
|
||||||
const { redis_key, token } = userStore.userInfo as UserInfo
|
const { redis_key, token } = userStore.userInfo as UserInfo
|
||||||
|
console.log("initMarketConditionsMQTT", redis_key, token)
|
||||||
await mqttClient.connect(import.meta.env.VITE_MQTT_TRANSACTION_HOST as string, {
|
await mqttClient.connect(import.meta.env.VITE_MQTT_TRANSACTION_HOST as string, {
|
||||||
username: `${redis_key}`,
|
username: `${redis_key}`,
|
||||||
password: `${token}`,
|
password: `${token}`,
|
||||||
|
|
@ -117,7 +117,7 @@ export const useTransactionStore = defineStore('transaction', () => {
|
||||||
* 关闭订阅,清空数组
|
* 关闭订阅,清空数组
|
||||||
* */
|
* */
|
||||||
const disconnect = () => {
|
const disconnect = () => {
|
||||||
mqttClient.disconnect()
|
mqttClient?.disconnect()
|
||||||
positionList.value = []
|
positionList.value = []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,5 +127,6 @@ export const useTransactionStore = defineStore('transaction', () => {
|
||||||
positionList,
|
positionList,
|
||||||
initMarketConditionsMQTT,
|
initMarketConditionsMQTT,
|
||||||
getPositionList,
|
getPositionList,
|
||||||
|
disconnect
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,108 @@
|
||||||
/**
|
|
||||||
* 帧级节流器数据项接口
|
|
||||||
*/
|
|
||||||
interface ThrottlerDataItem {
|
|
||||||
id: string | number;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* listFrameThrottler - 帧级节流器 -- 只用于持仓订单
|
* listFrameThrottler - 帧级节流器 -- 只用于持仓订单
|
||||||
* 收集同一帧内的所有数据,帧结束时只推送最后一个值
|
* 收集同一帧内的所有数据,帧结束时只推送最后一个值
|
||||||
*/
|
*/
|
||||||
export class ListFrameThrottler<T extends ThrottlerDataItem> {
|
|
||||||
private callback: (data: T) => void;
|
|
||||||
private pendingData: Record<string | number, T>;
|
|
||||||
private rafId: number | null;
|
|
||||||
|
|
||||||
constructor(callback: (data: T) => void) {
|
export type FrameThrottlerData = object;
|
||||||
this.callback = callback;
|
|
||||||
this.pendingData = {};
|
|
||||||
this.rafId = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
export type FrameThrottlerCallback = (data: FrameThrottlerData[]) => void;
|
||||||
* 推送数据(同一帧内多次调用只保留最后一个)
|
|
||||||
* @param data - 要推送的数据
|
|
||||||
*/
|
|
||||||
push(data: T): void {
|
|
||||||
// 将数据放入待处理数组
|
|
||||||
this.pendingData[data.id] = data;
|
|
||||||
|
|
||||||
// 如果还没有安排帧回调,则注册一个
|
export class ListFrameThrottler {
|
||||||
if (!this.rafId) {
|
private callback: FrameThrottlerCallback;
|
||||||
this.rafId = requestAnimationFrame(() => this._flush());
|
private pendingData: Map<string, FrameThrottlerData>;
|
||||||
}
|
private rafId: number | null;
|
||||||
|
private fallbackTimer: ReturnType<typeof setInterval> | null;
|
||||||
|
private isVisible: boolean;
|
||||||
|
|
||||||
|
constructor(callback: FrameThrottlerCallback) {
|
||||||
|
this.callback = callback;
|
||||||
|
this.pendingData = new Map();
|
||||||
|
this.rafId = null;
|
||||||
|
this.fallbackTimer = null;
|
||||||
|
this.isVisible = true;
|
||||||
|
this._bindVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 监听页面可见性变化
|
||||||
|
_bindVisibility() {
|
||||||
|
if (typeof document === 'undefined') return;
|
||||||
|
|
||||||
|
document.addEventListener('visibilitychange', () => {
|
||||||
|
this.isVisible = !document.hidden;
|
||||||
|
if (this.isVisible) {
|
||||||
|
// 切回前台:立即刷新积压数据
|
||||||
|
this._clearFallback();
|
||||||
|
this.flush();
|
||||||
|
} else {
|
||||||
|
// 切入后台:启动定时器兜底
|
||||||
|
this._startFallback();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 后台兜底:用 setTimeout 替代 rAF
|
||||||
|
private _startFallback() {
|
||||||
|
this._clearFallback();
|
||||||
|
this.fallbackTimer = setInterval(() => {
|
||||||
|
if (this.pendingData.size > 0) {
|
||||||
|
this._flush();
|
||||||
|
}
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _clearFallback() {
|
||||||
|
if (this.fallbackTimer) {
|
||||||
|
clearInterval(this.fallbackTimer);
|
||||||
|
this.fallbackTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 推送数据(同一帧内多次调用只保留最后一个)
|
||||||
|
*/
|
||||||
|
push(data: FrameThrottlerData) {
|
||||||
|
const dataRecord = data as Record<string, unknown>;
|
||||||
|
const key = String((dataRecord.id as string | number | undefined) ?? JSON.stringify(data));
|
||||||
|
this.pendingData.set(key, data);
|
||||||
|
|
||||||
|
if (!this.rafId) {
|
||||||
|
this.rafId = requestAnimationFrame(() => this._flush());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 帧结束时的回调:只推送最后一个数据
|
||||||
|
*/
|
||||||
|
_flush() {
|
||||||
|
this.rafId = null;
|
||||||
|
const list = [...this.pendingData.values()]
|
||||||
|
if (list.length === 0) return;
|
||||||
|
this.pendingData = new Map(); // 清空缓存
|
||||||
|
this.callback(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 立即刷新(手动触发)
|
||||||
|
*/
|
||||||
|
flush() {
|
||||||
|
if (this.rafId) {
|
||||||
|
cancelAnimationFrame(this.rafId);
|
||||||
|
this.rafId = null;
|
||||||
|
}
|
||||||
|
this._clearFallback();
|
||||||
|
this._flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁实例
|
||||||
|
*/
|
||||||
|
destroy() {
|
||||||
|
if (this.rafId) {
|
||||||
|
cancelAnimationFrame(this.rafId);
|
||||||
|
this.rafId = null;
|
||||||
|
}
|
||||||
|
this._clearFallback();
|
||||||
|
this.pendingData = new Map();
|
||||||
|
this.callback = () => {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 帧结束时的回调:只推送最后一个数据
|
|
||||||
*/
|
|
||||||
private _flush(): void {
|
|
||||||
this.rafId = null;
|
|
||||||
const list = Object.values(this.pendingData);
|
|
||||||
if (list.length === 0) return;
|
|
||||||
|
|
||||||
this.pendingData = {}; // 清空缓存
|
|
||||||
for (let i = 0; i < list.length; i++) {
|
|
||||||
this.callback(list[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 立即刷新(手动触发)
|
|
||||||
*/
|
|
||||||
flush(): void {
|
|
||||||
if (this.rafId) {
|
|
||||||
cancelAnimationFrame(this.rafId);
|
|
||||||
this.rafId = null;
|
|
||||||
}
|
|
||||||
this._flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 销毁实例
|
|
||||||
*/
|
|
||||||
destroy(): void {
|
|
||||||
if (this.rafId) {
|
|
||||||
cancelAnimationFrame(this.rafId);
|
|
||||||
this.rafId = null;
|
|
||||||
}
|
|
||||||
this.pendingData = {};
|
|
||||||
this.callback = () => {}; // 避免 null 后可能的调用问题,或保持 null 但需调整类型
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -77,6 +77,11 @@ const handleExport = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
transactionStore?.disconnect()
|
||||||
transactionStore.initMarketConditionsMQTT()
|
transactionStore.initMarketConditionsMQTT()
|
||||||
})
|
})
|
||||||
|
onUnmounted(()=>{
|
||||||
|
transactionStore?.disconnect()
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -9,16 +9,34 @@ export const search = [
|
||||||
]
|
]
|
||||||
|
|
||||||
export const tableColumns = [
|
export const tableColumns = [
|
||||||
|
// 账户ID
|
||||||
|
{ prop: 'account', label: '账户ID' ,width: '140px'},
|
||||||
// 订单号
|
// 订单号
|
||||||
{ prop: 'orderNo', label: '订单号' },
|
{ prop: 'orderNo', label: '订单号' ,width: '140px'},
|
||||||
// 操作类型
|
// 品种代码
|
||||||
{ prop: 'tradeType', label: '操作类型' },
|
{ prop: 'typeCode', label: '品种代码' ,width: '140px'},
|
||||||
// 金额
|
// 方向
|
||||||
{ prop: 'amount', label: '金额', isNumber: true },
|
{ prop: 'direction', label: '方向' ,width: '140px'},
|
||||||
// 交易数量
|
// 手数
|
||||||
{ prop: 'tradeQty', label: '交易数量'},
|
{ prop: 'lots', label: '手数', isNumber: true ,width: '140px'},
|
||||||
// 交易时间
|
// 买入价格
|
||||||
{ prop: 'tradeTime', label: '交易时间' },
|
{ prop: 'entryPrice', label: '买入价格', isNumber: true ,width: '140px'},
|
||||||
|
// 当前价格
|
||||||
|
{ prop: 'currentPrice', label: '当前价格', isNumber: true,width: '140px' },
|
||||||
|
// 止盈
|
||||||
|
{ prop: 'takeProfit', label: '止盈', isNumber: true,width: '140px' },
|
||||||
|
// 止损
|
||||||
|
{ prop: 'stopLoss', label: '止损', isNumber: true,width: '140px' },
|
||||||
// 浮动盈亏
|
// 浮动盈亏
|
||||||
{ prop: 'floatProfit', label: '浮动盈亏' },
|
{ prop: 'floatingPL', label: '浮动盈亏', isNumber: true ,width: '140px'},
|
||||||
|
// 保证金
|
||||||
|
{ prop: 'margin', label: '保证金', isNumber: true ,width: '140px'},
|
||||||
|
// 手续费
|
||||||
|
{ prop: 'commission', label: '手续费', isNumber: true,width: '140px' },
|
||||||
|
// 隔夜费
|
||||||
|
{ prop: 'overnightFee', label: '隔夜费', isNumber: true ,width: '140px'},
|
||||||
|
// 交易时间
|
||||||
|
{ prop: 'timestamp', label: '交易时间',width: '140px' },
|
||||||
|
// 带单人ID
|
||||||
|
{ prop: 'singleId', label: '带单人ID',width: '140px' },
|
||||||
]
|
]
|
||||||
|
|
@ -45,33 +45,31 @@
|
||||||
/>
|
/>
|
||||||
<context-menu-item
|
<context-menu-item
|
||||||
v-if="
|
v-if="
|
||||||
([1, 3, 4].includes(currentRow.role_id) && userStore!.userInfo!.role_id === 1) ||
|
([3, 4].includes(currentRow.role_id) && userStore!.userInfo!.role_id === 1)
|
||||||
([3, 4].includes(userStore!.userInfo!.role_id) &&
|
|
||||||
userStore!.userInfo!.role_id === currentRow.role_id)
|
|
||||||
"
|
"
|
||||||
label="设置停止接单金额"
|
label="设置停止接单金额"
|
||||||
@click="handleAction('acceptOrders')"
|
@click="handleAction('acceptOrders')"
|
||||||
/>
|
/>
|
||||||
<context-menu-item
|
<context-menu-item
|
||||||
v-if="
|
v-if="
|
||||||
([1, 3, 4].includes(currentRow.role_id) && userStore!.userInfo!.role_id === 1) ||
|
([3, 4].includes(currentRow.role_id) && userStore!.userInfo!.role_id === 1)
|
||||||
([3, 4].includes(userStore!.userInfo!.role_id) &&
|
|
||||||
userStore!.userInfo!.role_id === currentRow.role_id)
|
|
||||||
"
|
"
|
||||||
label="设置持仓转移金额"
|
label="设置持仓转移金额"
|
||||||
@click="handleAction('transfer')"
|
@click="handleAction('transfer')"
|
||||||
/>
|
/>
|
||||||
<context-menu-item
|
<context-menu-item
|
||||||
v-if="
|
v-if="
|
||||||
([1, 2, 3, 4].includes(userStore!.userInfo!.role_id) ||
|
([1, 2, 3, 4, 5].includes(userStore!.userInfo!.role_id) &&
|
||||||
(userStore!.userInfo!.role_id === 5 && (userStore!.userInfo as any).type === 1)) &&
|
userStore!.userInfo!.role_id === currentRow.role_id) || [1].includes(userStore!.userInfo!.role_id)
|
||||||
userStore!.userInfo!.role_id === currentRow.role_id
|
|
||||||
"
|
"
|
||||||
label="取款"
|
label="取款"
|
||||||
divided
|
divided
|
||||||
@click="handleAction('deposit')"
|
@click="handleAction('deposit')"
|
||||||
/>
|
/>
|
||||||
<context-menu-item label="存款" divided @click="handleAction('withdraw')" />
|
<context-menu-item
|
||||||
|
v-if="
|
||||||
|
[1].includes(userStore!.userInfo!.role_id)&&[3, 4].includes(currentRow.role_id)
|
||||||
|
" label="存款" divided @click="handleAction('withdraw')" />
|
||||||
</context-menu>
|
</context-menu>
|
||||||
|
|
||||||
<!-- 分页 -->
|
<!-- 分页 -->
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue