处理做市商列表

This commit is contained in:
2026-05-27 10:42:23 +08:00
parent d2b51ffe5f
commit 38d2cf7532
6 changed files with 155 additions and 97 deletions

View File

@ -26,15 +26,16 @@ interface PositionObj {
export const useOrderPositionStore = defineStore('orderPosition', () => {
const positionOrderList = ref<PositionObj[]>([])
const handleInfoListData = (positionObj: PositionObj) => {
if (positionObj?.orderNo) {
const existingIndex = positionOrderList.value.findIndex(
(p: PositionObj) => p.orderNo === positionObj.orderNo,
)
if (existingIndex !== -1) {
positionOrderList.value[existingIndex] = positionObj
const handleInfoListData = (list: PositionObj[]) => {
if (list?.length) {
for (let i = 0; i < list.length; i++) {
const idx = positionOrderList.value.findIndex((item)=>item.id === list[i]?.id)
if (idx !== -1) {
positionOrderList.value.splice(idx, 1, list[i] as PositionObj)
}else{
positionOrderList.value.unshift(positionObj)
positionOrderList.value.push(list[i] as PositionObj)
}
}
}
@ -45,6 +46,7 @@ export const useOrderPositionStore = defineStore('orderPosition', () => {
const handlePositionOrderList = async (item:string) => {
const fields = item.split(':')
console.log(fields)
const positionObj: PositionObj = {
id: fields[2], // 订单号
account: fields[0], // 账户id

View File

@ -56,7 +56,7 @@ export const useTransactionStore = defineStore('transaction', () => {
*/
const initMarketConditionsMQTT = async (): Promise<void> => {
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, {
username: `${redis_key}`,
password: `${token}`,
@ -117,7 +117,7 @@ export const useTransactionStore = defineStore('transaction', () => {
*
* */
const disconnect = () => {
mqttClient.disconnect()
mqttClient?.disconnect()
positionList.value = []
}
@ -127,5 +127,6 @@ export const useTransactionStore = defineStore('transaction', () => {
positionList,
initMarketConditionsMQTT,
getPositionList,
disconnect
}
})

View File

@ -1,35 +1,70 @@
/**
*
*/
interface ThrottlerDataItem {
id: string | number;
[key: string]: any;
}
/**
* 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;
export type FrameThrottlerCallback = (data: FrameThrottlerData[]) => void;
export class ListFrameThrottler {
private callback: FrameThrottlerCallback;
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 = {};
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;
}
}
/**
*
* @param data -
*/
push(data: T): void {
// 将数据放入待处理数组
this.pendingData[data.id] = data;
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());
}
@ -38,37 +73,36 @@ export class ListFrameThrottler<T extends ThrottlerDataItem> {
/**
*
*/
private _flush(): void {
_flush() {
this.rafId = null;
const list = Object.values(this.pendingData);
const list = [...this.pendingData.values()]
if (list.length === 0) return;
this.pendingData = {}; // 清空缓存
for (let i = 0; i < list.length; i++) {
this.callback(list[i]);
}
this.pendingData = new Map(); // 清空缓存
this.callback(list);
}
/**
*
*/
flush(): void {
flush() {
if (this.rafId) {
cancelAnimationFrame(this.rafId);
this.rafId = null;
}
this._clearFallback();
this._flush();
}
/**
*
*/
destroy(): void {
destroy() {
if (this.rafId) {
cancelAnimationFrame(this.rafId);
this.rafId = null;
}
this.pendingData = {};
this.callback = () => {}; // 避免 null 后可能的调用问题,或保持 null 但需调整类型
this._clearFallback();
this.pendingData = new Map();
this.callback = () => {};
}
}

View File

@ -77,6 +77,11 @@ const handleExport = () => {
})
}
onMounted(() => {
transactionStore?.disconnect()
transactionStore.initMarketConditionsMQTT()
})
onUnmounted(()=>{
transactionStore?.disconnect()
})
</script>

View File

@ -9,16 +9,34 @@ export const search = [
]
export const tableColumns = [
// 账户ID
{ prop: 'account', label: '账户ID' ,width: '140px'},
// 订单号
{ prop: 'orderNo', label: '订单号' },
// 操作类型
{ prop: 'tradeType', label: '操作类型' },
// 金额
{ prop: 'amount', label: '金额', isNumber: true },
// 交易数量
{ prop: 'tradeQty', label: '交易数量'},
// 交易时间
{ prop: 'tradeTime', label: '交易时间' },
{ prop: 'orderNo', label: '订单号' ,width: '140px'},
// 品种代码
{ prop: 'typeCode', label: '品种代码' ,width: '140px'},
// 方向
{ prop: 'direction', label: '方向' ,width: '140px'},
// 手数
{ prop: 'lots', label: '手数', isNumber: true ,width: '140px'},
// 买入价格
{ 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' },
]

View File

@ -45,33 +45,31 @@
/>
<context-menu-item
v-if="
([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)
([3, 4].includes(currentRow.role_id) && userStore!.userInfo!.role_id === 1)
"
label="设置停止接单金额"
@click="handleAction('acceptOrders')"
/>
<context-menu-item
v-if="
([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)
([3, 4].includes(currentRow.role_id) && userStore!.userInfo!.role_id === 1)
"
label="设置持仓转移金额"
@click="handleAction('transfer')"
/>
<context-menu-item
v-if="
([1, 2, 3, 4].includes(userStore!.userInfo!.role_id) ||
(userStore!.userInfo!.role_id === 5 && (userStore!.userInfo as any).type === 1)) &&
userStore!.userInfo!.role_id === currentRow.role_id
([1, 2, 3, 4, 5].includes(userStore!.userInfo!.role_id) &&
userStore!.userInfo!.role_id === currentRow.role_id) || [1].includes(userStore!.userInfo!.role_id)
"
label="取款"
divided
@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>
<!-- 分页 -->