Merge branch 'glms/feature/1.4.2' of http://git.yiliantech.com/gitlab/otc-dev/zszq-trs into glms/feature/1.4.2

This commit is contained in:
锦麟 王
2026-08-27 15:07:12 +08:00
2 changed files with 77 additions and 44 deletions
@@ -112,15 +112,22 @@ const vueTradeType = function () {
//标的选择组件(EQD-7049:改为服务端搜索,不再依赖全量 ylotc.underlyings,避免十几万标的整段下载卡死)
const vueUnderlying = function () {
const _suggestionTpl = _.template($('#underlyingSuggestionTpl').html());
// 标的缓存:按 品种|关键词 隔离;乱序响应由 token 丢弃(helper 收在函数内,避免全局绑定冲突)
// 标的缓存(同品种各实例共享):_cache 为最近一次服务端结果,_fresh 记录其对应的 品种|关键词,
// _seq 单调递增丢弃乱序/过期响应,_inflight 防同关键词重复请求(helper 收在函数内,避免全局绑定冲突)
const _cache = {};
const _tokens = {};
const _fresh = {};
const _seq = {};
const _inflight = {};
function _fetch(varietyId, query, cb) {
var key = (varietyId || 0) + '|' + (query || '');
var token = (_tokens[key] = (_tokens[key] || 0) + 1);
var vid = varietyId || 0;
var q = query || '';
var key = vid + '|' + q;
if (_inflight[key]) return;
var seq = (_seq[vid] = (_seq[vid] || 0) + 1);
_inflight[key] = true;
var postData = {
FilterCode: (query || '').toUpperCase(),
VarietyId: varietyId || 0,
FilterCode: q.toUpperCase(),
VarietyId: vid,
MaxShowLength: 20,
BlackLimit: 1,
UseForTrading: true,
@@ -128,7 +135,8 @@ const vueUnderlying = function () {
CheckLaunch: true
};
main.post('/frontdata/AjaxGetUnderlyingSelect', postData).done(function (res) {
if (_tokens[key] !== token) return; // 丢弃过期响应
delete _inflight[key];
if (_seq[vid] !== seq) return; // 已有更新的关键词发起请求,丢弃本响应
var arr = (res && (res.obj || res.data)) || [];
var norm = arr.map(function (x) {
return {
@@ -142,7 +150,11 @@ const vueUnderlying = function () {
PinYin: x.PinYin || ''
};
});
cb && cb(norm);
_cache[vid] = norm;
_fresh[vid] = key;
cb && cb(norm, q);
}).fail(function () {
delete _inflight[key];
});
}
function _filter(list, query, varietyId) {
@@ -163,24 +175,28 @@ const vueUnderlying = function () {
mounted() {
var self = this;
this.jqInput = $(this.$el).children(0);
// EQD-7049:预拉默认20条(当前品种),避免下拉空白
_fetch(self.underlying.VarietyId, '', function (list) {
_cache[self.underlying.VarietyId || 0] = list;
try { $(self.jqInput).autocomplete('search', ''); } catch (e) {}
});
// EQD-7049:预拉默认20条(当前品种),获得焦点时由插件自身的 onValueChange 呈现
_fetch(self.underlying.VarietyId, '');
this.autoctrl = FastVue.autocomplete(this.jqInput, {
valueField: 'Code',
lookup(query, callback) {
lookup(query) {
var varietyId = self.underlying.VarietyId;
var cached = _cache[varietyId || 0] || [];
var immediate = _filter(cached, query, varietyId);
if (query) {
// 有输入时异步向服务端搜索并刷新缓存(乱序响应由 token 丢弃
_fetch(varietyId, query, function (list) {
_cache[varietyId || 0] = list;
});
var vid = varietyId || 0;
var key = vid + '|' + (query || '');
if (_fresh[vid] === key) {
// 命中当前关键词的服务端结果:直接展示(服务端已按 StartsWith+品种/黑名单过滤,不再前端二次过滤
return (_cache[vid] || []).slice(0, 20);
}
return immediate;
// 异步搜索。FastVue 包装的 lookup 只同步取返回值渲染,服务端结果到达后必须重新触发
// onValueChange 才会显示;重走 lookup 时命中上面的 _fresh 分支直接返回,不会循环请求
_fetch(varietyId, query, function (list, q) {
var inst = self.jqInput.autocomplete();
if (!inst || !inst.visible) return; // 下拉已关闭:留待下次获得焦点时呈现
if ((self.jqInput.val() || '').toLowerCase() !== q.toLowerCase()) return; // 输入已变化:等新关键词的响应
inst.onValueChange();
});
// 过渡兜底:服务端响应到达前用旧缓存按关键词过滤,避免搜索期间下拉空白
return _filter(_cache[vid] || [], query, varietyId);
},
onSelect(data) {
if (self.underlying !== data) {
@@ -108,18 +108,26 @@ const vueTradeType = function () {
};
};
//标的选择组件(EQD-7049:改为服务端搜索,不再依赖全量 ylotc.underlyings,避免十几万标的整段下载卡死)
//标的选择组件(EQD-7049:改为服务端搜索,不再依赖全量 ylotc.underlyings,避免十几万标的整段下载卡死)
const vueUnderlying = function () {
const _suggestionTpl = _.template($('#underlyingSuggestionTpl').html());
// 标的缓存:按 品种|关键词 隔离;乱序响应由 token 丢弃(helper 收在函数内,避免全局绑定冲突)
// 标的缓存(同品种各实例共享):_cache 为最近一次服务端结果,_fresh 记录其对应的 品种|关键词,
// _seq 单调递增丢弃乱序/过期响应,_inflight 防同关键词重复请求(helper 收在函数内,避免全局绑定冲突)
const _cache = {};
const _tokens = {};
const _fresh = {};
const _seq = {};
const _inflight = {};
function _fetch(varietyId, query, cb) {
var key = (varietyId || 0) + '|' + (query || '');
var token = (_tokens[key] = (_tokens[key] || 0) + 1);
var vid = varietyId || 0;
var q = query || '';
var key = vid + '|' + q;
if (_inflight[key]) return;
var seq = (_seq[vid] = (_seq[vid] || 0) + 1);
_inflight[key] = true;
var postData = {
FilterCode: (query || '').toUpperCase(),
VarietyId: varietyId || 0,
FilterCode: q.toUpperCase(),
VarietyId: vid,
MaxShowLength: 20,
BlackLimit: 1,
UseForTrading: true,
@@ -127,7 +135,8 @@ const vueUnderlying = function () {
CheckLaunch: true
};
main.post('/frontdata/AjaxGetUnderlyingSelect', postData).done(function (res) {
if (_tokens[key] !== token) return; // 丢弃过期响应
delete _inflight[key];
if (_seq[vid] !== seq) return; // 已有更新的关键词发起请求,丢弃本响应
var arr = (res && (res.obj || res.data)) || [];
var norm = arr.map(function (x) {
return {
@@ -141,7 +150,11 @@ const vueUnderlying = function () {
PinYin: x.PinYin || ''
};
});
cb && cb(norm);
_cache[vid] = norm;
_fresh[vid] = key;
cb && cb(norm, q);
}).fail(function () {
delete _inflight[key];
});
}
function _filter(list, query, varietyId) {
@@ -162,24 +175,28 @@ const vueUnderlying = function () {
mounted() {
var self = this;
this.jqInput = $(this.$el).children(0);
// EQD-7049:预拉默认20条(当前品种),避免下拉空白
_fetch(self.underlying.VarietyId, '', function (list) {
_cache[self.underlying.VarietyId || 0] = list;
try { $(self.jqInput).autocomplete('search', ''); } catch (e) {}
});
// EQD-7049:预拉默认20条(当前品种),获得焦点时由插件自身的 onValueChange 呈现
_fetch(self.underlying.VarietyId, '');
this.autoctrl = FastVue.autocomplete(this.jqInput, {
valueField: 'Code',
lookup(query, callback) {
lookup(query) {
var varietyId = self.underlying.VarietyId;
var cached = _cache[varietyId || 0] || [];
var immediate = _filter(cached, query, varietyId);
if (query) {
// 有输入时异步向服务端搜索并刷新缓存(乱序响应由 token 丢弃
_fetch(varietyId, query, function (list) {
_cache[varietyId || 0] = list;
});
var vid = varietyId || 0;
var key = vid + '|' + (query || '');
if (_fresh[vid] === key) {
// 命中当前关键词的服务端结果:直接展示(服务端已按 StartsWith+品种/黑名单过滤,不再前端二次过滤
return (_cache[vid] || []).slice(0, 20);
}
return immediate;
// 异步搜索。FastVue 包装的 lookup 只同步取返回值渲染,服务端结果到达后必须重新触发
// onValueChange 才会显示;重走 lookup 时命中上面的 _fresh 分支直接返回,不会循环请求
_fetch(varietyId, query, function (list, q) {
var inst = self.jqInput.autocomplete();
if (!inst || !inst.visible) return; // 下拉已关闭:留待下次获得焦点时呈现
if ((self.jqInput.val() || '').toLowerCase() !== q.toLowerCase()) return; // 输入已变化:等新关键词的响应
inst.onValueChange();
});
// 过渡兜底:服务端响应到达前用旧缓存按关键词过滤,避免搜索期间下拉空白
return _filter(_cache[vid] || [], query, varietyId);
},
onSelect(data) {
if (self.underlying !== data) {