常规提交

This commit is contained in:
iFish 2014-06-26 22:24:54 +08:00
parent 1e5c679a48
commit c94dfc701c
27 changed files with 16456 additions and 440 deletions

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30324.0
VisualStudioVersion = 12.0.30516.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Web12306", "Web12306\Web12306.csproj", "{56406C67-2B6F-4152-9EC0-E6D80E86B96D}"
EndProject

View File

@ -142,6 +142,7 @@
<Content Include="css\ui\city-selector.css" />
<Content Include="css\ui\date-popup.css" />
<Content Include="css\ui\date-selector.css" />
<Content Include="css\ui\float-passenger-selector.css" />
<Content Include="css\ui\index-search-base.css" />
<Content Include="css\ui\options-param.css" />
<Content Include="css\ui\passenger-selector.css" />
@ -167,7 +168,6 @@
<Content Include="index.html" />
<Content Include="js\account\keepalive.js" />
<Content Include="js\account\sessionMgr.js" />
<Content Include="js\account\LoginUser.js" />
<Content Include="js\boot.js" />
<Content Include="css\fa\fonts\fontawesome-webfont.eot" />
<Content Include="css\fa\fonts\fontawesome-webfont.ttf" />
@ -182,14 +182,16 @@
<Content Include="js\platform\parser.js" />
<Content Include="js\platform\storage.js" />
<Content Include="js\platform\webRequest.js" />
<Content Include="js\profile\Profile.js" />
<Content Include="js\profile\ProfileList.js" />
<Content Include="js\station\station_data.js" />
<Content Include="js\ui\index.js" />
<Content Include="js\modules\jquery\jquery.js" />
<Content Include="js\modules\seajs\sea.js" />
<Content Include="js\modules\underscore\underscore.js" />
<Content Include="js\ui\ui-login.js" />
<Content Include="js\ui\ui-order-submit-process.js" />
<Content Include="js\ui\ui-passenger-selection.js" />
<Content Include="js\ui\ui-submit-order.js" />
<Content Include="js\ui\ui-trainlist.js" />
<Content Include="js\ui\widget.js" />
<Content Include="js\ui\widget_cityselector.js" />
<Content Include="js\ui\widget_datedropdown.js" />
@ -202,6 +204,7 @@
<Content Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</Content>
<Content Include="testdata\queryresult.json" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />

View File

@ -284,3 +284,19 @@ input[type="radio"] {
input[type="radio"]:checked {
background-position: 0 -582px;
}
div.text-input-wrap {
border: 1px solid #c9c9c9;
display: inline-block;
padding: 0 5px;
}
div.text-input-wrap > input {
border: none;
line-height: 22px;
padding: 2px 5px 2px 5px;
margin: 0;
background: transparent;
color: #6f7379;
display: inline-block;
}

View File

@ -74,3 +74,20 @@
width: 100%;
box-sizing: border-box;
}
select.normal {
padding: 5px;
background-color: #ffffff;
box-shadow: inset 0 0 5px 0 rgba(150,150,150,0.3);
width: 160px;
border: 1px solid #b5b5b5;
color: #737373;
}
select.normal:disabled {
color: #bbbbbb;
background-color: #f6f6f6;
border-color: #d9d9d9;
}
select.normal:focus {
outline: none;
}

View File

@ -13,6 +13,7 @@
@import url('ui/train-stops.css');
@import url('ui/widget-login.css');
@import url('ui/widget-ticketsubmit.css');
@import url('ui/float-passenger-selector.css');

View File

@ -0,0 +1,93 @@
#float-passenger-selector {
width: 550px;
color: #6f7379;
}
#float-passenger-selector select, #float-passenger-selector input {
color: #6f7379;
}
#float-passenger-selector .toolbar {
line-height: 26px;
}
#float-passenger-selector .toolbar > label {
line-height: 28px;
}
#float-passenger-selector .float-passenger-selector-list {
}
#float-passenger-selector .float-passenger-selector-list ul {
overflow: auto;
margin-top: 10px;
height: 100px;
line-height: 24px;
}
#float-passenger-selector .float-passenger-selector-list ul:empty:before {
content:'没有可以添加的联系人...';
color: #ccc;
}
#float-passenger-selector .float-passenger-selector-list ul.loading:empty:before {
content:'正在加载中...';
color: #ccc;
}
#float-passenger-selector .float-passenger-selector-list ul li {
float: left;
width: 95px;
}
#float-passenger-selector .float-passenger-selector-selected {
height: 210px;
}
#float-passenger-selector .float-passenger-selector-selected ul {
}
#float-passenger-selector .float-passenger-selector-selected ul:empty:before {
content: '请从列表中勾选联系人,最多添加五人';
color: #cccccc;
}
#float-passenger-selector .float-passenger-selector-selected ul li {
line-height: 30px;
padding-bottom: 5px;
}
#float-passenger-selector .float-passenger-selector-selected ul select {
margin-right: 10px;
}
#float-passenger-selector .float-passenger-selector-selected ul span {
width: 100px;
display: inline-block;
}
#float-passenger-selector .float-passenger-selector-selected ul span i {
cursor: pointer;
}
#float-passenger-selector .float-passenger-selector-selected ul span i:hover {
color: red;
}
#float-passenger-selector .float-passenger-selector-selected ul .passenger-seat {
width: 170px;
}
#float-passenger-selector .float-passenger-selector-selected ul .passenger-type {
width: 100px;
}
#float-passenger-selector .float-passenger-selector-selected ul a {
color: #C48747;
margin-left: 15px;
}
#float-passenger-selector .float-passenger-selector-selected ul a:hover {
color: #906130;
margin-left: 15px;
}
#float-passenger-selector footer {
text-align: right;
}

View File

@ -47,12 +47,18 @@
}
.result .train-seats {
padding: 20px 0;
padding: 20px 0 15px 0;
border: 1px solid #cccccc;
border-left: none;
line-height: 18px;
overflow: hidden;
}
.result .train-seats:empty:before {
content: '本车次车票已售完';
color: #cccccc;
}
.result .train-seats .row2 {
margin-top: 5px;
}
@ -72,13 +78,17 @@
}
.result .ticket-block {
display: inline-block;
display: block;
float: left;
border: 1px solid rgba(0, 0, 0, 0.2);
background: linear-gradient(to bottom, #ffffff, #ffffff 5%, #f5f5f5);
border-radius: 4px;
padding: 11px 16px;
color: #4e4e4e;
box-shadow: 0 1px 8px rgba(155, 155, 155, 0.2);
width: 105px;
margin-bottom: 5px;
margin-right: 5px;
}
.result .ticket-block-selected {

View File

@ -288,20 +288,23 @@
<p>{{=t.to.name}}</p>
</td>
<td class="train-seats">
{{for(var code in t.tickets){}}
<a href="javascript:void(0);" class="ticket-block">
<p><span>{{=ext.param.toSeatTypeName(code)}}</span></p>
{{~ext.param.seatDisplayOrder:code:cindex}}
{{
var t1=t.ticketMap[code];
if(!t1||!t1.count) continue;
}}
<a href="javascript:void(0);" class="ticket-block" data-traincode="{{=t.id}}" data-seatcode="{{=code}}">
<p><span>{{=t1.name}}</span></p>
<p class="row2">
<span class="ticket-num">{{=(t.tickets[code]?t.tickets[code]+"张":"无票")}} </span>
<span>¥{{=t.price["_"+code]/10}}</span>
<span class="ticket-num">{{=(t1.count?t1.count+"张":"无票")}} </span>
<span>¥{{=t1.price/10}}</span>
</p>
</a>
{{}}}
{{~}}
</td>
</tr>
{{~}}
</tbody>
</table>
</script>
@ -419,11 +422,71 @@
</p>
</div>
</section>
<section id="float-passenger-selector" class="float-dialog">
<header>
选择乘车人
<i class="fa fa-times cancel-button"></i>
</header>
<section class="float-passenger-selector-list">
<div class="toolbar">
<label>搜索联系人</label>
<div class="text-input-wrap">
<input type="text" value="" id="" placeholder="在列表中搜索..." />
<i class="fa fa-search"></i>
</div>
</div>
<script type="text/x-dot-template">
{{~it:p:i}}
<li data-name="{{!p.passenger_name}}" data-py="{{=p.first_letter}}" data-type="{{=p.passenger_type}}" data-idtype="{{=p.passenger_id_type_code}}" data-id="{{=p.passenger_id_no}}">
<label>
<input type="checkbox" value="" id="{{=p.key}}" />
{{!p.passenger_name}}
</label>
</li>
{{~}}
</script>
<ul></ul>
</section>
<section class="float-passenger-selector-selected">
<script type="text/x-dot-template">
<li data-id="{{=it.key}}">
<span>
<i class="fa fa-times-circle"></i>
&nbsp;
{{!it.passenger_name}}
</span>
<select class="passenger-seat normal">
{{~it.seats:s:i}}
<option value="{{=s.code}}">{{=s.name}}(¥{{=s.price/10}}元)</option>
{{~}}
</select>
<select class="passenger-type normal">
{{~it.ticketTypes:t:i}}
<option value="{{=t.id}}">{{=t.name}}</option>
{{~}}
</select>
{{?it.canAddChildren}}
<a href="javascript:;" class="add-child-ticket">
添加儿童票
</a>
{{?}}
</li>
</script>
<ul></ul>
</section>
<footer>
<a href="javascript:;" class="create-passenger" style="display:none;">添加联系人</a>
<button class="button button-primary">
<i class="fa fa-check-square"></i>
确认选择
</button>
</footer>
</section>
<script src="js/modules/jquery/jquery.js"></script>
<script src="js/modules/underscore/underscore.js"></script>
<script src="js/boot.js"></script>
<script src="js/modules/doT.js"></script>
<script src="js/modules/seajs/sea.js"></script>
<script src="js/boot.js"></script>
</body>
</html>

View File

@ -1,92 +0,0 @@
define(function (require) {
var eo = require("../platform/EventObject.js");
var passenger = require("../passenger/Passenger.js");
var passengerList = require("../passenger/PassengerList.js");
var Profile = require("../profile/Profile.js");
function LoginUser(name) {
var e = this;
var storagekey = "12306_user_" + name;
this.username = name || "";
this.dispname = name || "";
this.passengers = [];
this.savedProfile = Object.create(passengerList);
this.currentProfile = null;
this.rawPassenger = [];
this.options = {
showMore: false
};
this.save = function () {
localStorage[storagekey] = JSON.stringify(e);
e.fireEvent("userSaved");
};
//加载乘客信息
if (window.localStorage[storagekey]) {
var data = JSON.parse(window.localStorage[storagekey]);
$.extend(e, _.omit(data, "savedProfile", "passengers", "currentProfile"));
e.savedProfile = new ProfileList(data.savedProfile.list);
e.currentProfile = new Profile(data.currentProfile);
$.each(data.passengers, function () {
e.passengers.push(new Passenger(this.name, this.type, this.typename, this.idtype, this.idtypeName, this.id, this.firstLetter));
});
}
//重新加载乘客
this.reloadPassengers = function (rawPassenger) {
e.passengers = [];
e.rawPassenger = rawPassenger || [];
if (!ISOTN)
e.reloadPassengersOld();
else {
if (rawPassenger) {
$.each(rawPassenger, function () {
e.passengers.push(new Passenger(this.passenger_name, this.passenger_type, this.passenger_type_name, this.passenger_id_type_code, this.passenger_id_type_name, this.passenger_id_no, this.first_letter));
});
e.fireEvent("passengerLoaded");
e.save();
} else {
e.reloadPassengersOtn();
}
}
};
this.reloadPassengersOtn = function () {
otsweb.ajaxGet(message.host + "otn/confirmPassenger/getPassengerDTOs", message.host + "otn/leftTicket/init", null, "json").done(function (json) {
if (!json.status) {
alert("联系人加载失败,请重试。");
} else {
$.each(json.data.normal_passengers, function () {
e.rawPassenger.push(this);
e.passengers.push(new Passenger(this.passenger_name, this.passenger_type, this.passenger_type_name, this.passenger_id_type_code, this.passenger_id_type_name, this.passenger_id_no, this.first_letter));
});
e.fireEvent("passengerLoaded");
e.save();
}
}).fail(function () {
alert("联系人加载失败,请重试。");
});
};
//绑定事件
this.savedProfile.on("requireSave", e.save);
this.resetCurrentProfile = function (p) {
if (p) {
e.currentProfile = Object.create(Profile, p);
} else {
e.currentProfile = e.currentProfile || Object.create(Profile);
}
e.currentProfile.on("requireSave", e.save);
};
this.resetCurrentProfile();
return this;
}
LoginUser.prototype = Object.create(eo);
LoginUser.constructor = LoginUser;
return LoginUser;
});

View File

@ -4,23 +4,69 @@
var ajax = require("../platform/webRequest.js");
var storage = require("../platform/storage.js");
var keepAlive = require("../account/keepalive.js");
var passengers = null;
var currentuser = sessionStorage["_currentuser"];
var parser = require("../platform/parser.js");
if (sessionStorage["_passenger"])
passengers = JSON.parse(sessionStorage["_passenger"]);
//var LoginUser = require("./LoginUser.js");
var SessionMgr = function () {
var that = this;
var _passengerInLoad = false;
ev.apply(this, arguments);
var loadPassengers = function () {
if (!that.isLogined)
return;
if (_passengerInLoad)
return;
_passengerInLoad = true;
ajax.sendPost("confirmPassenger/getPassengerDTOs", "leftTicket/init", null, "json", function () {
_passengerInLoad = false;
var data = this.model;
if (!data || !data.data || !data.data.normal_passengers) {
passengers = null;
that.fireEvent("passengerLoadFailed");
that.fireEvent("passengerLoaded", passengers);
} else {
var p1 = data.data.normal_passengers;
passengers = _.filter(p1, parser.canPassageAddToOrder);
//对联系人数据进行预处理
parser.processPassenger(passengers);
if (p1.length !== passengers.length) {
that.fireEvent("notValidPassengerFound");
document.dispatchEvent(new Event("notValidPassengerFound"));
}
sessionStorage["_passenger"] = JSON.stringify(passengers);
that.fireEvent("passengerLoaded", passengers);
}
}, function () {
_passengerInLoad = false;
passengers = null;
sessionStorage.removeItem("_passenger");
that.fireEvent("passengerLoadFailed");
that.fireEvent("passengerLoaded", passengers);
});
};
that.checkLoginState = function (callback) {
ajax.sendGet("modifyUser/initQueryUserInfo", "", null, "text", function () {
if (this.text.indexOf("登录名:") !== -1) {
sessionStorage["_currentuser"] = "";
callback({ logined: false });
} else {
var m = /姓名:.*[\r\n]+<div[^>]+>([^<]+)<\/div>/i.exec(this.text) && RegExp.$1;
var status = /核验状态:[\w\W]+?>([^<>]+?)<\/div>/.exec(this.text) && RegExp.$1;
var un = /userDTO\.loginUserDTO\.user_name.*?value=['"]([^'"]+)['"]/.exec(this.text) && RegExp.$1;
sessionStorage["_currentuser"] = un;
if (!m || !status)
callback({ logined: false });
else {
@ -55,13 +101,9 @@
}
};
that.resetProfile = function () {
sessionStorage["_currentuser"] = "";
that.loadProfile("");
};
that.loadPassengers = function (force) {
if (!that.isLogined)
return;
};
that.save = function () {
if (!that.current)
return;
@ -69,6 +111,20 @@
var key = "12306_user_" + that.current.username;
storage.put(key, that.current);
};
that.getPassengers = function (callback) {
if (!callback)
return;
if (!that.isLogined) callback([]);
if (passengers)
callback(passengers);
else {
that.once("passengerLoaded", function () {
callback(passengers);
});
loadPassengers();
}
};
Object.defineProperty(this, "current", {
get: function () {
@ -77,10 +133,19 @@
set: function (v) {
if (session === v) return;
if (v) session = v;
if (v) {
if (v.username !== currentuser) {
sessionStorage["_currentuser"] = v.username;
sessionStorage.removeItem("_passenger");
passengers = null;
}
session = v;
}
else {
that.resetProfile();
}
console.log("sessionChanged fired.")
that.fireEvent("sessionChanged");
(that.isLogined && keepAlive.start()) || keepAlive.stop();
@ -91,13 +156,9 @@
return session && session.username || false;
}
});
//主动检测
that.checkLoginState(function (data) {
if (data.logined) {
that.loadProfile(data.username, data);
} else {
that.loadProfile("");
Object.defineProperty(this, "currentProfile", {
get: function () {
return session.currentProfile;
}
});
document.addEventListener("loginInvalid", function () {
@ -107,7 +168,17 @@
}
that.resetProfile();
});
this.loadProfile("");
//主动检测
if (typeof (currentuser) === "undefined") {
that.checkLoginState(function (data) {
if (data.logined) {
that.loadProfile(data.username, data);
} else {
that.loadProfile("");
}
});
} else
this.loadProfile(currentuser || "");
return this;
};

View File

@ -14,6 +14,57 @@
document.head.appendChild(script);
};
//extend jquery
$.fn.extend({
searchDelay: function (opts) {
var SearchDelay = function (e, opt) {
var __ = this;
this.$element = e;
this.timer = null;
this.opt = $.extend(SearchDelay.defaults, opt);
this.$element.keyup(function () {
__.reset();
__.timer = setTimeout(function () {
__.search.apply(__);
}, __.opt.delay);
});
};
SearchDelay.defaults = {
delay: 300
};
SearchDelay.prototype.search = function () {
this.$element.trigger("search", this.$element.val());
};
SearchDelay.prototype.reset = function () {
if (this.timer)
clearTimeout(this.timer);
};
SearchDelay.prototype.cancel = function () {
this.reset();
this.$element.val("");
this.search();
};
this.each(function () {
var key = "fish.searchdelay";
var $ele = $(this);
var target = $ele.data(key);
if (!target) {
target = new SearchDelay($ele, opts);
$ele.data(key, target);
}
if (typeof (opts) === "string") {
target[opts].apply(target, $.makeArray(arguments).slice(1));
}
});
return this;
}
}
);
//extend underscore
_.mixin({
mapObject: function (array, keySelector) {
@ -24,40 +75,68 @@
return obj;
}
});
//确保内容脚本启动
var start = $.Deferred();
start.done(function() {
loadScript("modules/seajs/sea.js", function() {
seajs.config({
base: basePath,
alias: {
"jquery": "modules/jquery/jquery.js",
"underscore": "modules/underscore/underscore.js"
},
vars: {
'locale': 'zh-cn'
},
charset: "utf-8",
debug: true
});
seajs.use("ui/" + pagename);
});
});
start.fail(function() {
alert("提示" ,"没有安装扩展!");
seajs.config({
base: basePath,
alias: {
"jquery": "modules/jquery/jquery.js",
"underscore": "modules/underscore/underscore.js"
},
vars: {
'locale': 'zh-cn'
},
charset: "utf-8",
debug: true
});
if (document.body.dataset["mobileSupportInitialized"]) {
start.resolve();
} else {
var timer = setTimeout(function() {
start.reject();
}, 3000);
document.addEventListener("mobileSupportInitialized", function () {
window.clearTimeout(timer);
start.resolve();
});
//检测扩展
var notInstallExtension = function () {
//TODO 没有安装扩展的提示
alert("没有检测到安装的订票助手扩展!");
//seajs.use("ui/noextension");
};
var targetExtension = [
"bpbefagpafkfgoihbmcgeileodldkpnf",
"gkbheeokbgmmnbjhhlphckobccejghjn"
];
window.targetExtensionId = null;
for (var id in targetExtension) {
var port = chrome.runtime.connect(targetExtension[id]);
try {
port.postMessage("");
port.disconnect();
window.targetExtensionId = targetExtension[id];
break;
} catch (e) {
}
}
if (!window.targetExtensionId) {
notInstallExtension();
} else {
//确保内容脚本启动
var start = $.Deferred();
start.done(function () {
chrome.runtime.sendMessage(window.targetExtensionId, { action: "getStorage" }, function (m) {
window.storage = m.detail;
seajs.use("ui/" + pagename);
});
});
start.fail(function () {
notInstallExtension();
});
if (document.body.dataset["mobileSupportInitialized"]) {
start.resolve();
} else {
var timer = setTimeout(function () {
start.reject();
}, 3000);
document.addEventListener("mobileSupportInitialized", function () {
window.clearTimeout(timer);
start.resolve();
});
}
}
})(window, document);

View File

@ -19,7 +19,8 @@
"2": "RZ",
"1": "YZ",
"0": "WZ",
"*": "QT"
"*": "QT",
"B": "HB"
};
exports.tagRevMap = _.invert(exports.tagOtnMap);
exports.seatNameMap = {
@ -32,13 +33,14 @@
"硬卧": "YW",
"软座": "RZ",
"硬座": "YZ",
"无座": "WZ"
"无座": "WZ",
"混编硬座": "HB"
};
exports.seatNameInvMap = _.invert(exports.seatNameMap);
exports.baseUri = "https://kyfw.12306.cn/otn/";
exports.queryBaseUri = "https://dynamic.12306.cn/otsquery/";
exports.toSeatTypeName = function(code) {
exports.toSeatTypeName = function (code) {
return exports.seatNameInvMap[exports.tagOtnMap[code]];
};
exports.seatDisplayOrder = '9PMO643210'.split('');
});

View File

@ -1,8 +1,9 @@
define(function (require, exports, module) {
var ajax = require("../platform/webRequest.js");
var param = require("../data.js");
var getTicketInfo = function (v) {
var data = {}, info = v.indexOf("#") === -1 ? v : /getSelected\(['"](.*?)['"]\)/i.exec(v)[1].split('#')[11],
var data = [], info = v.indexOf("#") === -1 ? v : /getSelected\(['"](.*?)['"]\)/i.exec(v)[1].split('#')[11],
match = info.match(/([A-Z\d])0*?([\*\d]{5})0*?(\d{4})/gi);
for (var j in match) {
@ -10,22 +11,25 @@
var sc = m[1];
var sp = m[2][0] == '*' ? null : parseInt(m[2], 10);
var st = parseInt(m[3], 10);
var seat = { code: sc, name: param.toSeatTypeName(sc), price: sp };
if (st < 3000) {
data[sc] = st;
data["_" + sc] = sp;
seat.count = st;
//TODO 二等软座提交是否和二等座一样都用的MO
//一等软座 7 二等软座 8
if (sc == "7") {
data['M'] = st;
data["_M"] = sp;
if (sc === "7") {
data.push({ code: 'M', name: param.toSeatTypeName('M'), price: sp, count: st });
}
else if (sc == "8") {
data['O'] = st;
data['_O'] = sp;
else if (sc === "8") {
data.push({ code: 'O', name: param.toSeatTypeName('O'), price: sp, count: st });
} else {
data.push(seat);
}
} else {
data['0'] = st - 3000;
data['_0'] = sp;
seat.count = st - 3000;
seat.code = '0';
seat.name = "无座";
data.push(seat);
}
};
return data;
@ -77,9 +81,9 @@
secureStr: t.secretStr,
selltime: null
};
var kp = _.pairs(getTicketInfo(t.queryLeftNewDTO.yp_info));
train.price = _.object(_.filter(kp, function (p) { return p[0][0] === '_'; }));
train.tickets = _.object(_.filter(kp, function (p) { return p[0][0] !== '_'; }));
var kp = getTicketInfo(t.queryLeftNewDTO.yp_info);
train.tickets = kp;
train.ticketMap = _.mapObject(kp, function (e) { return e.code; });
//起售时间
var selltimem = /(0*(\d+)月0*(\d+)日)?(\d+)\s*点\s*((\d+)分)?\s*起售/i.exec(t.buttonTextInfo.replace(/<.*?>/g, ''));

View File

@ -1,39 +1,72 @@
define(function() {
function EventObject() {
var e = this;
this.handles = {};
this.on = function (name, callback) {
var handleQueue = e.handles[name] || [];
e.handles[name] = handleQueue;
handleQueue.push(callback);
};
this.off = function (name, callback) {
var handleQueue = e.handles[name] || [];
if (callback) {
for (var i = handleQueue.length - 1; i >= 0; i++) {
if (handleQueue[i] == callback)
handleQueue.splice(i, 1);
}
} else {
handleQueue.length = 0;
}
e.handles[name] = handleQueue;
};
this.fireEvent = function (name, args) {
var handleQueue = e.handles[name];
if (!handleQueue) return;
for (var i in handleQueue) {
var handle = handleQueue[i];
if (!handle) continue;
if (handle.apply(this, args) === false)
break;
}
};
return this;
}
return EventObject;
define(function () {
function EventObject() {
var that = this;
var handles = {};
this.on = function (name, callback, once) {
var handleQueue = handles[name] || [];
handles[name] = handleQueue;
handleQueue.push(callback);
};
this.off = function (name, callback) {
var handleQueue = handles[name] || [];
if (callback) {
for (var i = handleQueue.length - 1; i >= 0; i--) {
if (handleQueue[i] === callback || (handleQueue[i].hasOwnProperty("__rawFn") && handleQueue[i].__rawFn === callback)) {
if (handleQueue[i].hasOwnProperty("__rawFn"))
delete handleQueue[i].__rawFn;
handleQueue.splice(i, 1);
}
}
} else {
handleQueue.length = 0;
}
handles[name] = handleQueue;
};
this.fireEvent = function (type) {
var ev = typeof (type) === "string" ? new Event(type) : type.type;
ev.target = ev.target || this;
var handleQueue = handles[type];
if (!handleQueue) return;
var args = [].slice.call(arguments, 1);
args.unshift(ev);
handleQueue = handleQueue.slice();
for (var i in handleQueue) {
var handle = handleQueue[i];
if (!handle) continue;
if (handle.apply(this, args) === false) {
ev.defaultPrevented = true;
break;
}
}
return !ev.defaultPrevented;
};
this.once = function (name, fn) {
var ptr = Function.prototype.apply.bind(fn.bind(this));
var nCallback = function () {
delete nCallback.__rawFn;
that.off(name, fn);
return ptr([].slice.call(arguments));
};
nCallback.__rawFn = fn;
that.on(name, nCallback);
};
this.addEventListener = this.on;
this.removeEventListener = this.off;
this.dispatchEvent = this.fireEvent;
return this;
}
return EventObject;
});

View File

@ -1,23 +1,5 @@
define(function (require, exports, module) {
var targetExtension = [
"bpbefagpafkfgoihbmcgeileodldkpnf",
"gkbheeokbgmmnbjhhlphckobccejghjn"
];
exports.targetId = null;
for (var id in targetExtension) {
var port = chrome.runtime.connect(targetExtension[id]);
try {
port.postMessage("");
port.disconnect();
exports.targetId = targetExtension[id];
break;
} catch (e) {
}
}
if (!exports.targetId)
document.dispatchEvent(new CustomEvent("supportError"));
exports.targetId = window.targetExtensionId;
exports.sendMessage = function(m, response) {
if (!exports.targetId)

View File

@ -37,4 +37,34 @@
}
return format;
};
exports.canPassageAddToOrder = function (p) {
if (p.passenger_id_type_code === "C" || p.passenger_id_type_code === "G" || p.passenger_id_type_code === "B")
return true;
if (p.passenger_id_type_code === "2")
return false;
return p.total_times === "93" || p.total_times === "95" || p.total_times === "97" || p.total_times === "99";
};
exports.getAvailableTicketType = function (p, stu) {
var a = [];
var pt = p.passenger_type;
if (pt === "3" && stu) {
a.push({ id: 3, name: "学生票" });
} else {
a.push({ id: 1, name: "成人票" });
a.push({ id: 2, name: "儿童票" });
}
if (pt === "4") {
a.push({ id: 4, name: "残军票" });
}
return a;
};
exports.processPassenger = function(list) {
list.forEach(function(e) {
e.key = e.passenger_type + "$" + e.passenger_name + "$" + e.passenger_id_type_code + "$" + e.passenger_id_no;
});
};
});

View File

@ -4,7 +4,7 @@
var Storage = function () {
var __ = this;
var st = {};
var st = window.storage|| {};
EventObject.apply(this, Array.prototype.slice.call(arguments));
@ -24,17 +24,13 @@
this.remove = function (key) {
delete st[key];
};
this.obj=function(key) {
this.obj = function (key) {
var value = __.get(key);
if (!value)
return null;
return JSON.parse(value);
}
extension.sendMessage({ action: "getStorage" }, function (m) {
st = m.detail;
});
};
Storage.prototype = Object.create(EventObject);
Storage.constructor = Storage;

View File

@ -1,63 +0,0 @@
define(function(require) {
var eo = require("../platform/EventObject.js");
function Profile(impdata) {
var __ = this;
this.name = "当前模式";
this.reset = function () {
__.selectedSeatType = ['O', '3', '1'];
__.selectedTrain = [];
__.selectSeatFirst = true;
__.hideNotInListTrain = false;
__.hideNoTicket = false;
__.hideNotSameFrom = false;
__.hideNotSameTo = false;
__.autoWaitToSell = true;
__.timeRangeDepFrom = 0;
__.timeRangeDepTo = 23;
__.timeRangeArrFrom = 0;
__.timeRangeArrTo = 23;
__.passengers = [];
__.dateloop = [];
__.partialSubmitEnabled = false; //是否允许部分提交
__.autoRefreshDelay = null; //null使用默认值
__.autoSubmitEnabled = false; //是否启用自动提交订单
__.studentTicket = false; //学生票?
__.fromText = ""; //始发站名称
__.toText = ""; //到站名称
__.fromCode = ""; //始发站电报码
__.toCode = ""; //到站电报码
__.depDate = ""; //出发日期
};
__.reset();
this.save = function () {
/// <summary>请求保存配置</summary>
__.fireEvent("requireSave");
};
if (impdata) {
$.extend(this, _.omit(impdata, "passengers", "selectedSeatType", "selectedTrain", "dateloop"));
var extAtt = ["selectedSeatType", "selectedTrain", "dateloop"];
_.each(extAtt, function (e) {
var att = e + '';
__[att] = _.clone(impdata[att]);
});
$.each(impdata.passengers, function () {
__.passengers.push(new Passenger(this.name, this.type, this.typename, this.idtype, this.idtypeName, this.id, this.firstLetter));
});
}
return this;
}
Profile.prototype = Object.create(eo);
Profile.constructor = Profile;
return Profile;
});

View File

@ -1,49 +0,0 @@
define(function(require) {
var eo = require("../platform/EventObject.js");
var $ = require("jquery");
function ProfileList(imptlist) {
var __ = this;
this.list = [];
this.add = function (p) {
if (!p || !(p instanceof Profile)) return;
p.on("requireSave", function () {
__.save();
});
__.list.push(p);
__.fireEvent("added", [p]);
__.save();
};
this.remove = function (p) {
var idx = __.list.indexOf(p);
if (idx == -1) return;
__.list.splice(idx, 1);
__.fireEvent("removed", [p]);
__.save();
};
this.save = function () {
__.fireEvent("requireSave");
};
this.find = function (name) {
return _.find(__.list, function (e) { return e.name == name; });
};
if (imptlist) {
$.each(imptlist, function () {
__.list.push(new Profile(this));
});
}
return this;
}
ProfileList.prototype = Object.create(eo);
ProfileList.constructor = ProfileList;
return ProfileList;
});

File diff suppressed because one or more lines are too long

View File

@ -16,6 +16,9 @@
ev.apply(this, arguments);
this.init = function() {
};
this.showLoginDialog = function () {
var info = storage.obj("12306_lastUser");
if (info) {
@ -129,7 +132,6 @@
};
var loginSuccess = function () {
btn.prop("disabled", false);
that.closeLoginDialog();
loginTip.setState("ok", "您已成功登录!");
loginTip.delayClose();
@ -139,10 +141,17 @@
pwd: pwd
});
sessionMgr.loadProfile(un);
that.dispatchEvent("loginSuccess");
that.closeLoginDialog();
};
loadLoginAsyncSuggest();
};
dlg.on("closeDialog", function() {
that.fireEvent("closeLogin");
}).on("openDialog", function() {
that.fireEvent("showLogin");
});
sessionMgr.on("sessionChanged", function () {

View File

@ -0,0 +1,65 @@
define(function (require, exports, module) {
var ps = require("./ui-passenger-selection.js");
var so = require("./ui-submit-order.js");
var param = require("../data.js");
var ui_login = require("./ui-login.js");
var sessMgr = require("../account/sessionMgr.js");
//提交参数
var pTrain, pSeat, pStu, pPassengers;
exports.init = function () {
ps.init();
so.init();
ps.on("passengerSelected", function () {
pPassengers = ps.selectedPassenger;
exports.showConfirmOrderUi();
});
};
exports.start = function (train, seat, stu, passengers) {
if (train) {
pTrain = train;
pSeat = seat;
pStu = stu;
pPassengers = passengers;
}
if (!pTrain)
return;
if (!sessMgr.isLogined) {
ui_login.once("loginSuccess", exports.start);
ui_login.showLoginDialog();
return;
}
if (!pPassengers || !pPassengers.length)
exports.showPassengerSelectUi();
else {
exports.showConfirmOrderUi();
}
};
ui_login.on("closeLogin", function () {
ui_login.off("loginSuccess", exports.start);
});
exports.showPassengerSelectUi = function () {
ps.show(pPassengers, pTrain, pSeat, pStu);
};
exports.showConfirmOrderUi = function () {
so.showOrderUi(pTrain, pSeat, pStu, pPassengers);
};
exports.showSuccessUi = function () {
};
exports.showFailedUi = function (msg) {
};
});

View File

@ -0,0 +1,149 @@
define(function (require, exports, module) {
var EO = require("../platform/EventObject.js");
var widget = require("./widget.js");
var sessMgr = require("../account/sessionMgr.js");
var param = require("../data.js");
var parser = require("../platform/parser.js");
var mp = require("./widget_message_popup.js");
//变量
var listTpl = $("section.float-passenger-selector-list script").doT();
var rowTpl = $("section.float-passenger-selector-selected script").doT();
var extTplData = {
p: param
};
var PassengerSelectionUI = function () {
var that = this;
var selectedPassenger = [];
var allPassengers = [];
var preloadPasList = null, curTrain = null, isStu = false, curSeat;
EO.apply(this);
this.init = function () {
};
this.show = function (passengers, train, seat, stu) {
preloadPasList = passengers;
curTrain = train;
isStu = stu;
curSeat = seat;
widget.showFloatDialog($("#float-passenger-selector"));
//加载联系人?
var list = $("section.float-passenger-selector-list ul");
list.empty().addClass("loading");
$("#float-passenger-selector .float-passenger-selector-selected ul").empty();
selectedPassenger = [];
sessMgr.getPassengers(function (paslist) {
allPassengers = paslist;
list.removeClass("loading");
list.html(listTpl(_.filter(paslist, function (p) {
return stu === "0" || p.passenger_type === '3';
}), extTplData));
});
};
this.hide = function () {
};
this.filterPassenger = function () {
var key = this.value;
var list = $("#float-passenger-selector .float-passenger-selector-list li");
if (!key) {
list.show();
} else {
list.hide();
key = key.toLowerCase();
list.each(function () {
var ds = this.dataset;
if (ds.py.toLowerCase().indexOf(key) !== -1 || ds.name.toLowerCase().indexOf(key) !== -1 || ds.id.toLowerCase().indexOf(key) !== -1)
$(this).show();
});
}
};
Object.defineProperty(this, "selectedPassenger", {
get: function () {
return selectedPassenger;
}
});
//绑定事件-搜索
$("#float-passenger-selector .toolbar input:text").searchDelay().on("search", this.filterPassenger);
//绑定事件-添加
$(document).on("change", "#float-passenger-selector .float-passenger-selector-list input:checkbox", function () {
var isAdd = this.checked;
var id = this.id;
if (isAdd) {
if (selectedPassenger.length >= 5) {
mp.showMessagePopup("error", "联系人最多只能选择五个哦");
this.checked = false;
return;
}
var p = _.findWhere(allPassengers, { key: id });
if (!p)
return;
var x = _.clone(p);
selectedPassenger.push(x);
//初始化席别和票种
x.ticketTypes = parser.getAvailableTicketType(x, isStu);
x.seats = curTrain.tickets;
x.canAddChildren = x.passenger_type === "1";
$("#float-passenger-selector .float-passenger-selector-selected ul").append(rowTpl(x, extTplData));
} else {
selectedPassenger = _.reject(selectedPassenger, function (e) {
return e.key === id;
});
$("#float-passenger-selector .float-passenger-selector-selected li[data-id='" + id + "']").remove();
}
});
$(document).on("click", "#float-passenger-selector .float-passenger-selector-selected i.fa-times-circle", function () {
//删除
var li = $(this).closest("li");
var id = li.attr("data-id");
li.remove();
var chk = document.getElementById(id);
chk && (chk.checked = false);
});
$(document).on("click", "#float-passenger-selector .float-passenger-selector-selected a.add-child-ticket", function () {
if (selectedPassenger.length >= 5) {
mp.showMessagePopup("error", "联系人最多只能选择五个哦");
return;
}
var li = $(this).closest("li");
var id = li.attr("data-id");
var p = _.clone(_.findWhere(allPassengers, { key: id }));
p.passenger_type = "2";
parser.processPassenger([p]);
selectedPassenger.push(p);
p.ticketTypes = [{ id: 2, name: "儿童票" }];
p.seats = curTrain.tickets;
p.canAddChildren = false;
li.after(rowTpl(p, extTplData));
});
//确定按钮
$("#float-passenger-selector footer button.button-primary").click(function () {
if (selectedPassenger.length === 0) {
mp.showMessagePopup("error", "还没有选择乘客的说 :-(");
return;
}
that.fireEvent("passengerSelected");
widget.hideFloatDialog($("#float-passenger-selector"));
});
};
PassengerSelectionUI.prototype = Object.create(EO);
PassengerSelectionUI.constructor = EO;
return new PassengerSelectionUI();
});

View File

@ -0,0 +1,22 @@
define(function(require, exports, module) {
var EventObject = require("../platform/EventObject.js");
var widget = require("./widget.js");
var SubmitOrderUi = function() {
var that = this;
EventObject.apply(this);
this.init = function() {
};
this.showOrderUi = function(train, passenger) {
widget.showFloatDialog($("#ticket-submit-container"));
};
return this;
};
SubmitOrderUi.prototype = Object.create(EventObject);
SubmitOrderUi.constructor = SubmitOrderUi;
module.exports = new SubmitOrderUi();
});

View File

@ -0,0 +1,63 @@
define(function (require, exports, module) {
var queryResult = null;
var param = require("../data.js");
var tpl = $("#train_table").doT();
var sessMgr = require("../account/sessionMgr.js");
var ticketQuery = require("./../otn/queryticket.js");
var EventObject = require("../platform/EventObject.js");
var TrainListObj = function () {
var __ = this;
EventObject.apply(this);
var loadTestData = function () {
$.getJSON("/testdata/queryresult.json").done(function (data) {
queryResult = data;
__.renderResultList();
});
};
this.renderResultList = function (data) {
data = data || queryResult;
$("#result").html(tpl(data, {
param: param
}));
};
this.load = function (from, to, date, stu) {
ticketQuery
.queryTicket(from, to, date, stu)
.done(function () {
queryResult = this;
__.renderResultList();
}).fail(function () {
});
};
this.init = function () {
loadTestData();
};
//监听订票请求
$(document).on("click", "a.ticket-block", function() {
var id = this.dataset.traincode;
var seatcode = this.dataset.seatcode;
var train = _.findWhere(queryResult.original, { id: id });
if (!train)
return;
__.dispatchEvent("requireSubmitOrder", {
train: train,
seat: seatcode
});
});
return this;
};
TrainListObj.prototype = Object.create(EventObject);
TrainListObj.constructor = TrainListObj;
module.exports = new TrainListObj();
});

View File

@ -1,75 +1,89 @@
define(function (require, exports) {
var mask = $('<div id="mask"></div>');
var maskCallback = [];
var unmaskCallback = [];
document.body.appendChild(mask[0]);
//当动画完成后,如果没有显示的必要,那么就移除它。
//这里没有考虑没有如果没有这个事件触发的情况
mask.on("transitionend", function () {
var cb = null;
if (!mask.hasClass("final")) {
mask.hide();
while (cb = unmaskCallback.shift())
cb.call(mask);
} else {
while (cb = maskCallback.shift())
cb.call(mask);
}
});
//将当前对象置于居中的位置,并允许以指定方式做便宜
var centerEle = function (e, offsety) {
var width = e.width();
var height = e.height();
offsety = offsety || 20;
e.css("margin-left", "-" + (width / 2) + "px");
e.css("margin-top", "-" + (height / 2 + offsety) + "px");
if (!e.hasClass("float-dialog"))
e.addClass("float-dialog");
};
var maskScreen = exports.mask = function (callback) {
if (callback)
maskCallback.push(callback);
mask.height(document.body.scrollHeight + "px");
mask.show();
setTimeout(function () { mask.addClass("final"); }, 10);
};
var unmaskScreen = exports.unmask = function (callback) {
if (callback)
maskCallback.push(callback);
mask.removeClass("final");
};
exports.showFloatDialog = function (ele, callback) {
centerEle(ele);
maskScreen(function () {
ele.show();
ele.animate({ opacity: 'show', "margin-top": "+=20px" }, 'fast', 'linear', callback);
});
};
exports.hideFloatDialog = function (ele, callback) {
ele.animate({ opacity: 'hide', "margin-top": "-=20px" }, 'fast', 'linear', function () {
unmaskScreen(callback);
});
};
//监听文档级别事件,显示悬浮窗
$(document).on("refreshDialog.widget", function () {
var e = $(this);
var height = e.height();
e.animate({ top: "-" + (height / 2) + "px" }, 'fast', 'linear');
});
$(document).on("click.widget", ".float-dialog .cancel-button", function () {
exports.hideFloatDialog($(this).closest(".float-dialog"));
});
define(function (require, exports) {
var mask = $('<div id="mask"></div>');
var maskCallback = [];
var unmaskCallback = [];
var maskEleCount = 0;
document.body.appendChild(mask[0]);
//当动画完成后,如果没有显示的必要,那么就移除它。
//这里没有考虑没有如果没有这个事件触发的情况
mask.on("transitionend", function () {
var cb = null;
if (!mask.hasClass("final")) {
mask.hide();
while (cb = unmaskCallback.shift())
cb.call(mask);
} else {
while (cb = maskCallback.shift())
cb.call(mask);
}
});
//将当前对象置于居中的位置,并允许以指定方式做便宜
var centerEle = function (e, offsety) {
var width = e.width();
var height = e.height();
offsety = offsety || 20;
e.css("margin-left", "-" + (width / 2) + "px");
e.css("margin-top", "-" + (height / 2 + offsety) + "px");
if (!e.hasClass("float-dialog"))
e.addClass("float-dialog");
};
var maskScreen = exports.mask = function (callback) {
if (mask.hasClass("final")) {
if (callback) callback();
return;
}
if (callback)
maskCallback.push(callback);
mask.height(document.body.scrollHeight + "px");
mask.show();
setTimeout(function () { mask.addClass("final"); }, 10);
};
var unmaskScreen = exports.unmask = function (callback) {
if (callback)
maskCallback.push(callback);
mask.removeClass("final");
};
exports.showFloatDialog = function (ele, callback) {
if (ele.is(":visible")) {
if (callback) callback();
return;
}
maskEleCount++;
centerEle(ele);
maskScreen(function () {
ele.show();
ele.animate({ opacity: 'show', "margin-top": "+=20px" }, 'fast', 'linear', callback);
});
ele.trigger("openDialog");
};
exports.hideFloatDialog = function (ele, callback) {
maskEleCount--;
ele.animate({ opacity: 'hide', "margin-top": "-=20px" }, 'fast', 'linear', function () {
if (!maskEleCount)
unmaskScreen(callback);
});
ele.trigger("closeDialog");
};
//监听文档级别事件,显示悬浮窗
$(document).on("refreshDialog.widget", function () {
var e = $(this);
var height = e.height();
e.animate({ top: "-" + (height / 2) + "px" }, 'fast', 'linear');
});
$(document).on("click.widget", ".float-dialog .cancel-button", function () {
exports.hideFloatDialog($(this).closest(".float-dialog"));
});
});

15481
Web12306/testdata/queryresult.json vendored Normal file

File diff suppressed because it is too large Load Diff