425 lines
13 KiB
JavaScript
425 lines
13 KiB
JavaScript
|
define(function (require, exports, module) {
|
|||
|
var data = require("../data.js");
|
|||
|
var sessmgr = require("../account/sessionMgr.js");
|
|||
|
var query = require("../otn/queryticket.js");
|
|||
|
var utility = require("../utility.js");
|
|||
|
var cachedSuggest = JSON.parse(localStorage['trainTransit'] || '{"key":"", "data":null}');
|
|||
|
var loadTime = 1000;
|
|||
|
var mp = require("./widget_message_popup.js");
|
|||
|
|
|||
|
//DOM
|
|||
|
var listContainer = $("#oncetrainsit");
|
|||
|
var listTemplate = listContainer.find(">script").doT();
|
|||
|
var listTarget = listContainer.find(">section");
|
|||
|
|
|||
|
var cp = sessmgr.currentProfile;
|
|||
|
sessmgr.on("currentProfileChanged", function () {
|
|||
|
cp = sessmgr.currentProfile;
|
|||
|
});
|
|||
|
|
|||
|
var isInQuery = false;
|
|||
|
var startQueryLimit = data.startTrainStationSuggestQueryLimit;
|
|||
|
var isSuggestLoopDisabled = false;
|
|||
|
var isSuggestReported = false;
|
|||
|
|
|||
|
//当前查询结果
|
|||
|
var currentResult = null;
|
|||
|
var forceShowSuggestion = false;
|
|||
|
var showlevel = 1;
|
|||
|
var currentTransit;
|
|||
|
var queryQueue, queryKeyQueue;
|
|||
|
var queryLoopTimer = null;
|
|||
|
var lastLoopKey = null;
|
|||
|
|
|||
|
var calculateTimeForCompare = function (trainClass, minutes) {
|
|||
|
var rate = 1.0;
|
|||
|
switch (trainClass) {
|
|||
|
case 'G':
|
|||
|
rate = 1.0;
|
|||
|
break;
|
|||
|
case 'D':
|
|||
|
rate = 0.71428;
|
|||
|
break;
|
|||
|
case 'Z':
|
|||
|
rate = 0.45714;
|
|||
|
break;
|
|||
|
case 'T':
|
|||
|
rate = 0.4;
|
|||
|
break;
|
|||
|
default:
|
|||
|
rate = 0.28571;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return Math.floor(rate * minutes);
|
|||
|
};
|
|||
|
|
|||
|
var setQueryResult = function (result, queryCount) {
|
|||
|
currentResult = result;
|
|||
|
var cacheKey = cp.fromCode + cp.toCode + cp.depDate;
|
|||
|
if (!isAutoShowTransit())
|
|||
|
return false;
|
|||
|
|
|||
|
|
|||
|
if (cachedSuggest.key === cacheKey) {
|
|||
|
if (cachedSuggest.data === null)
|
|||
|
return true;
|
|||
|
|
|||
|
//load result;
|
|||
|
isInQuery = true;
|
|||
|
|
|||
|
var cdata = _.clone(cachedSuggest.data);
|
|||
|
prepareData(cdata);
|
|||
|
renderTransitResult(cdata);
|
|||
|
} else {
|
|||
|
//判断检测等级
|
|||
|
//1-自动检测换乘,要求车次在4趟以下,无始发终到
|
|||
|
//2-不建议换乘,在上述条件以外
|
|||
|
|
|||
|
var url = "http://12306.fishlee.net/tt/tor?date=" + cp.depDate + "&from=" + cp.fromCode + "&to=" + cp.toCode + "&maxAge=" + getCalcBasedTime();
|
|||
|
var dlg = forceShowSuggestion ? mp.showMessagePopup("loading", "查询换乘中,请稍等...") : null;
|
|||
|
$.get(url).done(function (resp) {
|
|||
|
if (!resp || !resp.ret) {
|
|||
|
dlg.setState("error", (resp && resp.msg) || "咱的服务器计算不过来了,请等等服务器...");
|
|||
|
dlg.delayClose();
|
|||
|
isInQuery = false;
|
|||
|
return;
|
|||
|
}
|
|||
|
cachedSuggest.key = cacheKey;
|
|||
|
cachedSuggest.data = _.clone(resp.data);
|
|||
|
localStorage['trainTransit'] = JSON.stringify(cachedSuggest);
|
|||
|
|
|||
|
if (!resp.data)
|
|||
|
return;
|
|||
|
|
|||
|
prepareData(resp.data);
|
|||
|
renderTransitResult(resp.data);
|
|||
|
if (dlg)
|
|||
|
dlg.close();
|
|||
|
}).fail(function () {
|
|||
|
if (dlg) {
|
|||
|
dlg.setState("error", "咱的服务器计算不过来了,请等等服务器...");
|
|||
|
dlg.delayClose();
|
|||
|
isInQuery = false;
|
|||
|
}
|
|||
|
});
|
|||
|
isInQuery = true;
|
|||
|
}
|
|||
|
|
|||
|
return true;
|
|||
|
};
|
|||
|
|
|||
|
var prepareData = function (result) {
|
|||
|
//城市
|
|||
|
var corder = result.corder;
|
|||
|
var line;
|
|||
|
|
|||
|
result.corderName = [];
|
|||
|
for (var j = 0; j < corder.length; j++) {
|
|||
|
var city = data.cities[corder[j]];
|
|||
|
if (!city) {
|
|||
|
corder.splice(j, 1);
|
|||
|
j--;
|
|||
|
} else {
|
|||
|
result.corderName.push(city.n);
|
|||
|
}
|
|||
|
}
|
|||
|
//推荐线路
|
|||
|
result.recommandLines = _.map(result.toplines, function (index) { return result.lines[index]; });
|
|||
|
//线路
|
|||
|
var lines = result.lines;
|
|||
|
for (var i = 0; i < lines.length; i++) {
|
|||
|
line = lines[i];
|
|||
|
line.first.fromName = data.getCityName(line.first.from);
|
|||
|
line.first.toName = data.getCityName(line.first.to);
|
|||
|
line.second.fromName = data.getCityName(line.second.from);
|
|||
|
line.second.toName = data.getCityName(line.second.to);
|
|||
|
|
|||
|
if (!line.second.fromName || !line.second.toName || !line.first.fromName || !line.first.toName) {
|
|||
|
lines.splice(i, 1);
|
|||
|
i--;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//时间
|
|||
|
line.first.leftShort = /\s(\d+:\d+)/.exec(line.first.left) && RegExp.$1;
|
|||
|
line.first.arriveShort = /\s(\d+:\d+)/.exec(line.first.arrive) && RegExp.$1;
|
|||
|
line.first.days = utility.getDaysDifference(line.first.left, line.first.arrive);
|
|||
|
line.first.elapsedStr = utility.formatMinutesToShortStr(line.first.elapsed);
|
|||
|
|
|||
|
line.second.leftShort = /\s(\d+:\d+)/.exec(line.second.left) && RegExp.$1;
|
|||
|
line.second.arriveShort = /\s(\d+:\d+)/.exec(line.second.arrive) && RegExp.$1;
|
|||
|
line.second.leftDays = utility.getDaysDifference(line.first.left, line.second.left);
|
|||
|
line.second.arriveDays = utility.getDaysDifference(line.first.left, line.second.arrive);
|
|||
|
line.second.elapsedStr = utility.formatMinutesToShortStr(line.second.elapsed);
|
|||
|
|
|||
|
line.totalTimeStr = utility.formatMinutesToShortStr(line.total);
|
|||
|
line.waitTimeStr = utility.formatMinutesToShortStr(line.wait);
|
|||
|
}
|
|||
|
|
|||
|
//过滤推荐线路
|
|||
|
for (var k = 0; k < result.recommandLines.length; k++) {
|
|||
|
line = result.recommandLines[k];
|
|||
|
if (!line.second.fromName || !line.second.toName || !line.first.fromName || !line.first.toName) {
|
|||
|
result.recommandLines.splice(k, 1);
|
|||
|
k--;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var renderTransitResult = function (result) {
|
|||
|
if (result) {
|
|||
|
currentTransit = result;
|
|||
|
|
|||
|
if (forceShowSuggestion) {
|
|||
|
listContainer.slideDown();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (showlevel == 1)
|
|||
|
currentTransit.showLines = currentTransit.recommandLines;
|
|||
|
else if (showlevel == 2) {
|
|||
|
currentTransit.showLines = _.where(currentTransit.lines, { ne: false });
|
|||
|
if (!currentTransit.showLines || !currentTransit.showLines.length)
|
|||
|
currentTransit.showLines = currentTransit.lines;
|
|||
|
}
|
|||
|
else currentTransit.showLines = currentTransit.lines;
|
|||
|
|
|||
|
var html = listTemplate(currentTransit, {
|
|||
|
u: utility,
|
|||
|
d: data,
|
|||
|
l: showlevel
|
|||
|
});
|
|||
|
|
|||
|
listTarget.html(html);
|
|||
|
|
|||
|
queryQueue = _.groupBy(_.flatten(_.map(currentTransit.showLines, function (line) { return [line.first, line.second]; })), function (seg) {
|
|||
|
seg.key = seg.from + "," + seg.fromName + "," + seg.to + "," + seg.toName + "," + seg.left.split(' ')[0];
|
|||
|
seg.queryData = seg.key.split(',');
|
|||
|
seg.queryData.push(false);
|
|||
|
seg.queryData.push(false);
|
|||
|
seg.queryData.push(true);
|
|||
|
seg.queryData.push(true);
|
|||
|
seg.queryData.push(false);
|
|||
|
seg.target = null;
|
|||
|
|
|||
|
return seg.key;
|
|||
|
});
|
|||
|
queryKeyQueue = _.keys(queryQueue);
|
|||
|
loadTime = 1000;
|
|||
|
lastLoopKey = null;
|
|||
|
startQueryTimer();
|
|||
|
};
|
|||
|
|
|||
|
var getCalcBasedTime = function () {
|
|||
|
var times = _.map(currentResult.original, function (t) {
|
|||
|
return calculateTimeForCompare(t.code[0], utility.parseTimeSpanToMinutes(t.elapsedTime.total));
|
|||
|
});
|
|||
|
|
|||
|
return times.length ? (_.max(times) + _.min(times)) / 2 : 999999;
|
|||
|
};
|
|||
|
|
|||
|
var isAutoShowTransit = function () {
|
|||
|
if (forceShowSuggestion)
|
|||
|
return true;
|
|||
|
|
|||
|
//无效数据,或车次数大于4
|
|||
|
if (!currentResult || !currentResult.original || currentResult.original.length >= 4) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
//如果存在始发终到车
|
|||
|
if (_.some(currentResult.original, function (x) {
|
|||
|
return x.from.endpoint && x.to.endpoint;
|
|||
|
}))
|
|||
|
return false;
|
|||
|
|
|||
|
return true;
|
|||
|
};
|
|||
|
|
|||
|
var closeTransitSuggest = function () {
|
|||
|
clearQueryTimer();
|
|||
|
isSuggestLoopDisabled = true;
|
|||
|
listContainer.slideUp();
|
|||
|
};
|
|||
|
|
|||
|
var clearQueryTimer = function () {
|
|||
|
if (!queryLoopTimer)
|
|||
|
return;
|
|||
|
|
|||
|
clearInterval(queryLoopTimer);
|
|||
|
queryLoopTimer = null;
|
|||
|
};
|
|||
|
|
|||
|
var startQueryTimer = function () {
|
|||
|
if (queryLoopTimer)
|
|||
|
return;
|
|||
|
|
|||
|
queryLoopTimer = setTimeout(queryLoop, loadTime);
|
|||
|
};
|
|||
|
|
|||
|
var queryLoop = function () {
|
|||
|
if (!queryKeyQueue || !queryKeyQueue.length)
|
|||
|
return;
|
|||
|
|
|||
|
var key = queryKeyQueue.shift();
|
|||
|
var trains = queryQueue[key];
|
|||
|
queryKeyQueue.push(key);
|
|||
|
lastLoopKey = lastLoopKey || key;
|
|||
|
|
|||
|
var date = trains[0].queryData[4];
|
|||
|
var trainCodes = _.groupBy(trains, function (x) {
|
|||
|
return x.train.code;
|
|||
|
});
|
|||
|
|
|||
|
var processResponse = function (loaded, result) {
|
|||
|
queryLoopTimer = null;
|
|||
|
|
|||
|
_.each(_.keys(trainCodes), function (code) {
|
|||
|
var ele = listTarget.find("tr.ticket-container td[data-date='" + date + "'][data-traincode='" + code + "']");
|
|||
|
ele.empty();
|
|||
|
if (!loaded) {
|
|||
|
ele.append("<span class='remark remark-warning'>查询发生错误</span>");
|
|||
|
} else if (result.notInSellTime) {
|
|||
|
ele.append("<span class='remark remark-warning'>当日车次不在预售期</span>");
|
|||
|
//从列表中移除,这个车次之后不用再查了。
|
|||
|
delete queryQueue[key];
|
|||
|
queryKeyQueue.pop();
|
|||
|
} else if (result.selltime) {
|
|||
|
ele.append("<span class='remark remark-primary'>" + utility.format + "</span>");
|
|||
|
} else {
|
|||
|
//显示余票信息
|
|||
|
var train = _.findWhere(result.original, { code: code });
|
|||
|
if (!train) {
|
|||
|
//车次不存在,可能是过程中会自动变号的车次
|
|||
|
ele.closest("tr").prevUntil(".header, .ticket-container").andSelf().remove();
|
|||
|
|
|||
|
//从列表中移除
|
|||
|
var args = _.clone(trainCodes[code]);
|
|||
|
args.unshift(trains);
|
|||
|
queryQueue[key] = _.without.apply(this, args);
|
|||
|
|
|||
|
console.log("中转站查询:找不到车次 " + code + ", 查询信息:" + key);
|
|||
|
|
|||
|
//从缓存的信息中移除。
|
|||
|
var matchedLines = _.filter(currentTransit.lines, function (line) {
|
|||
|
return _.some(trainCodes[code], function (t) { return t === line.first || t === line.second; });
|
|||
|
});
|
|||
|
delete trainCodes[code];
|
|||
|
if (matchedLines && matchedLines.length) {
|
|||
|
matchedLines.unshift(currentTransit.lines);
|
|||
|
currentTransit.lines = _.without.apply(this, matchedLines);
|
|||
|
|
|||
|
matchedLines[0] = currentTransit.recommandLines;
|
|||
|
currentTransit.recommandLines = _.without.apply(this, matchedLines);
|
|||
|
}
|
|||
|
} else if (train.limitSellInfo) {
|
|||
|
//限售信息
|
|||
|
ele.append("<span class='remark remark-warning'>" + train.limitSellInfo + "</span>");
|
|||
|
delete trainCodes[code];
|
|||
|
} else if (train.selltime) {
|
|||
|
ele.append("<span class='remark remark-primary'>" + utility.formatSellDate(train.limitSellInfo) + "</span>");
|
|||
|
} else if (train.available < 1) {
|
|||
|
ele.append("<span class='remark remark-warning'>本车次暂无可售票</span>");
|
|||
|
} else {
|
|||
|
_.each(trainCodes[code], function (t) {
|
|||
|
t.secureStr = train.secureStr;
|
|||
|
t.rtrain = train;
|
|||
|
});
|
|||
|
//显示车次车票
|
|||
|
var tickets = [];
|
|||
|
_.each(data.seatDisplayOrder, function (seat) {
|
|||
|
var seatinfo = train.ticketMap[seat];
|
|||
|
//不显示无票以及没有的席别
|
|||
|
if (!seatinfo || !seatinfo.count) return;
|
|||
|
|
|||
|
var selected = cp && $.inArray(seat, cp.selectedSeatType) !== -1;
|
|||
|
tickets.push("<button class='button button-" + (selected ? "primary" : "default") + " btn-ticket-block' data-seatcode='" + seat + "' data-traincode='" + code + "' data-sec='" + train.secureStr + "' data-transmit='1'>" + seatinfo.name + " " + seatinfo.count + "张 " + (seatinfo.price > 0 ? "¥" + (seatinfo.price / 10) : "") + "</button>");
|
|||
|
});
|
|||
|
ele.append(tickets.join(""));
|
|||
|
}
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
if (!_.keys(trainCodes).length && queryQueue[key]) {
|
|||
|
//已经没有车次了。。移除
|
|||
|
delete queryQueue[key];
|
|||
|
queryKeyQueue.pop();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
query.queryTicket.apply(this, trains[0].queryData)
|
|||
|
.done(function () {
|
|||
|
processResponse(true, this);
|
|||
|
}).fail(function () {
|
|||
|
processResponse(false);
|
|||
|
}).always(function () {
|
|||
|
if (queryKeyQueue[0] === lastLoopKey) {
|
|||
|
loadTime = 5000;
|
|||
|
|
|||
|
if (listContainer.find("table tr").length > 1) {
|
|||
|
listContainer.slideDown();
|
|||
|
queryLoopTimer = setTimeout(queryLoop, loadTime);
|
|||
|
}
|
|||
|
} else {
|
|||
|
queryLoopTimer = setTimeout(queryLoop, loadTime);
|
|||
|
}
|
|||
|
});
|
|||
|
};
|
|||
|
|
|||
|
listContainer.on("change", "input[name=tt_level]", function () {
|
|||
|
showlevel = listContainer.find("input[name=tt_level]:checked").val();
|
|||
|
renderTransitResult();
|
|||
|
});
|
|||
|
listContainer.find(">header>a").click(closeTransitSuggest);
|
|||
|
|
|||
|
var ctx = {
|
|||
|
setQueryResult: function (result, queryCount) {
|
|||
|
if (cp.resign || cp.studentTicket || isSuggestLoopDisabled)
|
|||
|
return false;
|
|||
|
if ((queryCount < startQueryLimit && !forceShowSuggestion) || isInQuery || isSuggestLoopDisabled)
|
|||
|
return isInQuery;
|
|||
|
|
|||
|
return setQueryResult(result, queryCount);
|
|||
|
},
|
|||
|
clearQueryResultCache: function () {
|
|||
|
isSuggestLoopDisabled = false;
|
|||
|
isSuggestReported = false;
|
|||
|
isInQuery = false;
|
|||
|
forceShowSuggestion = false;
|
|||
|
clearQueryTimer();
|
|||
|
},
|
|||
|
findTrain: function (secstr) {
|
|||
|
var train = _.findWhere(_.flatten(_.map(_.values(currentTransit.lines), function (t) { return [t.first, t.second]; })), { secureStr: secstr });
|
|||
|
return train && train.rtrain;
|
|||
|
}
|
|||
|
};
|
|||
|
Object.defineProperty(ctx, "isInSuggestQuery", {
|
|||
|
get: function () {
|
|||
|
return isInQuery;
|
|||
|
},
|
|||
|
set: function (value) {
|
|||
|
isInQuery = value;
|
|||
|
}
|
|||
|
});
|
|||
|
Object.defineProperty(ctx, "isSuggestLoopDisabled",
|
|||
|
{
|
|||
|
get: function () {
|
|||
|
return isSuggestLoopDisabled;
|
|||
|
},
|
|||
|
set: function (value) {
|
|||
|
isSuggestLoopDisabled = value;
|
|||
|
}
|
|||
|
});
|
|||
|
Object.defineProperty(ctx, "forceTransit",
|
|||
|
{
|
|||
|
get: function () {
|
|||
|
return forceShowSuggestion;
|
|||
|
},
|
|||
|
set: function (value) {
|
|||
|
forceShowSuggestion = value;
|
|||
|
}
|
|||
|
});
|
|||
|
|
|||
|
return ctx;
|
|||
|
});
|