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 queuedcount = 0; 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 = data.onceTransitApi + "?date=" + cp.depDate + "&from=" + cp.fromCode + "&to=" + cp.toCode + "&maxAge=" + getCalcBasedTime(); var dlg = forceShowSuggestion ? mp.showMessagePopup("loading", "查询换乘中,请稍等...", { closeAfter: null }) : 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); line.transitWarning = line.ne && line.wait < 150; } //过滤推荐线路 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(); } } var cp1 = cp || {}; port.track(data.trackTypes.TRANSIT_SHOWTRANSIT, [cp1.fromCode || "", cp1.toCode || "", cp1.depDate || ""]); 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; queuedcount = queryKeyQueue.length; 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 || currentResult.noAction) { 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(); //恢复按钮显示 if (!cp.studentTicket) $(".train-list-func").parent().show(); }; var clearQueryTimer = function () { if (!queryLoopTimer) return; clearInterval(queryLoopTimer); queryLoopTimer = null; }; var startQueryTimer = function () { if (queryLoopTimer) return; queryLoopTimer = setTimeout(queryLoop, loadTime); }; var sortTables = function () { var table = $("#oncetrainsit table"); var trs = table.find("tr:gt(0)"); var array = []; for (var i = 0; i < trs.length; i += 3) { var subArray = [trs.get(i), trs.get(i + 1), trs.get(i + 2)]; subArray.originalIndex = i; array.push(subArray); } //排序 array.sort(function (x, y) { var offset = x.originalIndex - y.originalIndex; var wx = parseInt(x[2].children[0].dataset.available) + parseInt(x[2].children[1].dataset.available); if (isNaN(wx)) return offset; var wy = parseInt(y[2].children[0].dataset.available) + parseInt(y[2].children[1].dataset.available); if (isNaN(wy)) return offset; if (wy !== wx) return wy - wx; return offset; }); var df = document.createDocumentFragment(); _.each(_.flatten(array), function (row) { df.appendChild(row); }); table.append(df); }; var queryLoop = function () { if (!queryKeyQueue || !queryKeyQueue.length) return; var key = queryKeyQueue.shift(); var trains = queryQueue[key]; queryKeyQueue.push(key); var date = trains[0].queryData[4]; var from = trains[0].from; var to = trains[0].to; var trainIds = _.groupBy(trains, function (x) { return x.train.id; }); var processResponse = function (loaded, result) { queryLoopTimer = null; _.each(_.keys(trainIds), function (tid) { var ele = listTarget.find("tr.ticket-container td[data-date='" + date + "'][data-trainid='" + tid + "'][data-fromcode='" + from + "'][data-tocode='" + to + "']"); ele.empty(); if (!loaded) { ele.append("未能查询余票信息,等待重新查询"); ele.attr("data-available", 0); } else if (result.notInSellTime) { ele.append("当日车次不在预售期"); ele.attr("data-available", 1); } else if (result.selltime) { ele.append("" + utility.format + ""); } else { //显示余票信息 var train = _.findWhere(result.original, { id: tid }); if (!train) { //车次不存在,可能是过程中会自动变号的车次 ele.closest("tr").prevUntil(".header, .ticket-container").andSelf().remove(); //从列表中移除 var args = _.clone(trainIds[tid]); args.unshift(trains); queryQueue[key] = _.without.apply(this, args); //从缓存的信息中移除。 var matchedLines = _.filter(currentTransit.lines, function (line) { return _.some(trainIds[tid], function (t) { return t === line.first || t === line.second; }); }); delete trainIds[tid]; 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("" + train.limitSellInfo + ""); delete trainIds[tid]; ele.attr("data-available", 1); } else if (train.selltime) { ele.append("" + utility.formatSellDate(train.selltime) + "起售"); ele.attr("data-available", 1); } else if (train.available < 1) { ele.append("本车次暂无可售票"); ele.attr("data-available", 0); } else { _.each(trainIds[tid], function (t) { t.secureStr = train.secureStr; t.rtrain = train; }); //显示车次车票 var tickets = []; var hasSelected = false; _.each(data.seatDisplayOrder, function (seat) { var seatinfo = train.ticketMap[seat]; //不显示无票以及没有的席别 if (!seatinfo || !seatinfo.count) return; var selected = cp && $.inArray(seat, cp.selectedSeatType) !== -1; hasSelected |= selected; tickets.push("" + seatinfo.name + " " + seatinfo.count + "张 " + (seatinfo.price > 0 ? "¥" + (seatinfo.price / 10) : "") + ""); }); ele.append(tickets.join("")); ele.attr("data-available", hasSelected ? 3 : 2); } } }); if (result.notInSellTime || !_.keys(trainIds).length && queryQueue[key]) { //从列表中移除,这个车次之后不用再查了。 delete queryQueue[key]; queryKeyQueue.pop(); } sortTables(); } query.queryTicket.apply(this, trains[0].queryData) .done(function () { processResponse(true, this); }).fail(function () { processResponse(false); }).always(function () { if (!isInQuery || isSuggestLoopDisabled) return; if (--queuedcount === 0) { loadTime = 5000; if (listContainer.find("table tr").length > 1) { listContainer.slideDown(); //自动滚屏一下下 setTimeout(function () { var pos = $("#oncetrainsit").position(); if (pos && pos.top) { window.scrollTo(0, pos.top); } }, 1000); 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(); $("#oncetrainsit .loading").remove(); }, 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; });