jquery-seat-charts 使用-自定义座位号 及 重新加载数据
来源:互联网 发布:网络信息安全协会 编辑:程序博客网 时间:2024/05/13 06:18
原创 2015年10月24日 10:41:41
- 标签:
- jquery
一.自定义座位号(即重新加载数据源)
例子
1.自定义数据
[html] view plain copy
- var data1 = [['aa1','aa2','aa3','aa4','aa5','aa6'],['bb1','bb2','bb3','bb4','bb5','bb6'],['cc1','cc2','cc3','cc4','cc5','cc6']];
2.html传输数据
[html] view plain copy
- naming: {//设置行列等信息
- top: false, //不显示顶部横坐标(行)
- // rows: ['3', '2', '1'],
- // columns: ['A', 'B', 'C', 'G', 'D', 'F'],
- getLabel: function(character, row, column) { //返回房间信息
- return column;
- },
- getData:function(dataList){
- console.log(dataList)
- return dataList;
- },
- data:data1
- },
3.源码修改 大概400行左右,修改lable
[html] view plain copy
- seats[id] = new seat({
- id : id,
- label : naming.data[row][column] ,
- // label : overrideLabel ? overrideLabel : naming.getLabel(character, naming.rows[row], naming.columns[column]),
- row : row,
- column : column,
- character : character
- });
4.源码修改,25行左右 加入data参数
[html] view plain copy
- settings = {
- animate : false, //requires jQuery UI
- naming : {
- top : true,
- left : true,
- getId : function(character, row, column) {
- return row + '_' + column;
- },
- getLabel : function (character, row, column) {
- return column;
- },
- data:[]
- },
二.重新刷新数据
修改源码 在开始的位置
[html] view plain copy
- if (this.data('seatCharts')) {
- // console.log(this.data('seatCharts'))
- // return this.data('seatCharts');
- // console.log(setup)
- // console.log(setup.legend.items)
- // console.log(this.data('seatCharts'))
- var ary = setup.legend.items;
- ary.splice(0,ary.length);
- this.empty();
- }
html
[html] view plain copy
- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>test</title>
- <link rel="stylesheet" type="text/css" href="css/roomchartcommon.css" />
- <script type="text/javascript" src="js/jquery-1.11.2.js"></script>
- <script type="text/javascript" src="js/jquery.seat-charts.js"></script>
- <script type="text/javascript">
- var price = 100; //房间价
- var beforeroom;
- var $cart = $('#rooms_selected'), //房间区
- $rooms_num = $('#rooms_num'), //房间数
- $total_price = $('#rooms_price'); //总金额
- $roomNo = $('#roomNo');//房间号
- $roomMsg = $('#roomMsg');//房间信息
- var sc ;
- var data1 = [['aa1','aa2','aa3','aa4','aa5','aa6'],['bb1','bb2','bb3','bb4','bb5','bb6'],
- ['cc1','cc2','cc3','cc4','cc5','cc6']];
- var data2 = [['dd1','dd2','dd3','dd4','dd5','dd6'],['ee1','ee2','ee3','ee4','ee5','ee6'],
- ['ff1','ff2','ff3','ff4','ff5','ff6']];
- $(document).ready(function() {
- initchart(data1);
- });
- function initchart(dataList){
- sc = $('#room_area').seatCharts({
- map: [//房间结构图 f 代表已入住;e 代表未入住; 下划线 "_" 代表过道
- 'ffffff',
- 'eeeeee',
- 'ffeeee'
- ],
- seats: {//设置已入住和未入住相关属性
- f: {
- price: 125,
- classes: 'first-class',
- category: '已入住'
- },
- e: {
- price: 70,
- classes: 'economy-class',
- category: '未入住'
- }
- },
- naming: {//设置行列等信息
- top: false, //不显示顶部横坐标(行)
- // rows: ['3', '2', '1'],
- // columns: ['A', 'B', 'C', 'G', 'D', 'F'],
- getLabel: function(character, row, column) { //返回房间信息
- return column;
- },
- getData:function(dataList){
- console.log(dataList)
- return dataList;
- },
- data:dataList
- },
- legend: {//定义图例
- node: $('#roomlegend'),
- items: [
- ['f', 'available', '未入住'],
- ['e', 'available', '将到期'],
- ['f', 'unavailable', '已入住']
- ]
- },
- click: function() {
- if (this.status() == 'available') { //若为可选状态,添加响应事件
- var roomNoText = $('<li>' + this.settings.label + '号</li>')
- .attr('id', 'cart-item-' + this.settings.id)
- .data('seatId', this.settings.id).text();
- $roomNo.text(roomNoText);
- var roomMsgHtml = '<span>没有入住信息</span><br><input type="button" class="roominbtn" value="入住"/>';
- $roomMsg.html(roomMsgHtml);
- return 'selected';
- $('<li>' + (this.settings.row + 1) + this.settings.label + '号</li>')
- .attr('id', 'cart-item-' + this.settings.id)
- .data('seatId', this.settings.id)
- .appendTo($cart);
- $rooms_num.text(sc.find('selected').length + 1); //统计选票数量
- $total_price.text(getTotalPrice(sc) + price);//计算票价总金额
- return 'selected';
- } else if (this.status() == 'selected') { //若为选中状态
- $rooms_num.text(sc.find('selected').length - 1);//更新票数量
- $total_price.text(getTotalPrice(sc) - price);//更新票价总金额
- $('#cart-item-' + this.settings.id).remove();//删除已预订座位
- return 'available';
- } else if (this.status() == 'unavailable') { //若为损坏状态
- var roomNoText = $('<li>' + this.settings.label + '号</li>')
- .attr('id', 'cart-item-' + this.settings.id)
- .data('seatId', this.settings.id).text();
- console.log(roomNoText);
- $roomNo.text(roomNoText);
- var roomMsgText = "张三、李四、王五、马六";
- $roomMsg.text(roomMsgText);
- return 'unavailable';
- } else {
- return this.style();
- }
- }
- });
- //设置已售出的座位
- sc.get(['3_03', '2_05']).status('unavailable');
- }
- function refresh(){
- // console.log(sc);
- // sc.dataReload(data2)
- initchart(data2)
- }
- </script>
- </head>
- <body>
- <button style="float:right;width:150px;height:30px;" onclick="refresh()">刷新图表</button>
- <div class="roomcontent">
- <div id="room_area">
- </div>
- <div id="roomlegend" class='of'></div>
- <div id="roomdetail">
- <h3>房间详细信息</h3>
- <div id="roomNo">
- </div>
- <div id="roomMsg">
- </div>
- </div>
- </div>
- </body>
- </html>
源码
[html] view plain copy
- /*
- * jQuery-Seat-Charts v1.1.0
- */
- (function($) {
- $.fn.seatCharts = function (setup) {
- //if there's seatCharts object associated with the current element, return it
- if (this.data('seatCharts')) {
- // console.log(this.data('seatCharts'))
- // return this.data('seatCharts');
- // console.log(setup)
- // console.log(setup.legend.items)
- // console.log(this.data('seatCharts'))
- var ary = setup.legend.items;
- ary.splice(0,ary.length);
- this.empty();
- }
- var fn = this,
- seats = {},
- seatIds = [],
- legend,
- settings = {
- animate : false, //requires jQuery UI
- naming : {
- top : true,
- left : true,
- getId : function(character, row, column) {
- return row + '_' + column;
- },
- getLabel : function (character, row, column) {
- return column;
- },
- data:[]
- },
- legend : {
- node : null,
- items : []
- },
- click : function() {
- if (this.status() == 'available') {
- return 'selected';
- } else if (this.status() == 'selected') {
- return 'available';
- } else {
- return this.style();
- }
- },
- focus : function() {
- if (this.status() == 'available') {
- return 'focused';
- } else {
- return this.style();
- }
- },
- blur : function() {
- return this.status();
- },
- seats : {}
- },
- //seat will be basically a seat object which we'll when generating the map
- seat = (function(seatCharts, seatChartsSettings) {
- return function (setup) {
- var fn = this;
- fn.settings = $.extend({
- status : 'available', //available, unavailable, selected
- style : 'available',
- //make sure there's an empty hash if user doesn't pass anything
- data : seatChartsSettings.seats[setup.character] || {}
- //anything goes here?
- }, setup);
- fn.settings.$node = $('<div></div>');
- fn.settings.$node
- .attr({
- id : fn.settings.id,
- role : 'checkbox',
- 'aria-checked' : false,
- focusable : true,
- tabIndex : -1 //manual focus
- })
- .text(fn.settings.label)
- .addClass(['seatCharts-seat', 'seatCharts-cell', 'available'].concat(
- //let's merge custom user defined classes with standard JSC ones
- fn.settings.classes,
- typeof seatChartsSettings.seats[fn.settings.character] == "undefined" ?
- [] : seatChartsSettings.seats[fn.settings.character].classes
- ).join(' '));
- //basically a wrapper function
- fn.data = function() {
- return fn.settings.data;
- };
- fn.char = function() {
- return fn.settings.character;
- };
- fn.node = function() {
- return fn.settings.$node;
- };
- /*
- * Can either set or return status depending on arguments.
- *
- * If there's no argument, it will return the current style.
- *
- * If you pass an argument, it will update seat's style
- */
- fn.style = function() {
- return arguments.length == 1 ?
- (function(newStyle) {
- var oldStyle = fn.settings.style;
- //if nothing changes, do nothing
- if (newStyle == oldStyle) {
- return;
- }
- //focused is a special style which is not associated with status
- fn.settings.status = newStyle != 'focused' ? newStyle : fn.settings.status;
- fn.settings.$node
- .attr('aria-checked', newStyle == 'selected');
- //if user wants to animate status changes, let him do this
- seatChartsSettings.animate ?
- fn.settings.$node.switchClass(oldStyle, newStyle, 200) :
- fn.settings.$node.removeClass(oldStyle).addClass(newStyle);
- return fn.settings.style = newStyle;
- })(arguments[0]) : fn.settings.style;
- };
- //either set or retrieve
- fn.status = function() {
- return fn.settings.status = arguments.length == 1 ?
- fn.style(arguments[0]) : fn.settings.status;
- };
- //using immediate function to convienietly get shortcut variables
- (function(seatSettings, character, seat) {
- //attach event handlers
- $.each(['click', 'focus', 'blur'], function(index, callback) {
- //we want to be able to call the functions for each seat object
- fn[callback] = function() {
- if (callback == 'focus') {
- //if there's already a focused element, we have to remove focus from it first
- if (seatCharts.attr('aria-activedescendant') !== undefined) {
- seats[seatCharts.attr('aria-activedescendant')].blur();
- }
- seatCharts.attr('aria-activedescendant', seat.settings.id);
- seat.node().focus();
- }
- /*
- * User can pass his own callback function, so we have to first check if it exists
- * and if not, use our default callback.
- *
- * Each callback function is executed in the current seat context.
- */
- return fn.style(typeof seatSettings[character][callback] === 'function' ?
- seatSettings[character][callback].apply(seat) : seatChartsSettings[callback].apply(seat));
- };
- });
- //the below will become seatSettings, character, seat thanks to the immediate function
- })(seatChartsSettings.seats, fn.settings.character, fn);
- fn.node()
- //the first three mouse events are simple
- .on('click', fn.click)
- .on('mouseenter', fn.focus)
- .on('mouseleave', fn.blur)
- //keydown requires quite a lot of logic, because we have to know where to move the focus
- .on('keydown', (function(seat, $seat) {
- return function (e) {
- var $newSeat;
- //everything depends on the pressed key
- switch (e.which) {
- //spacebar will just trigger the same event mouse click does
- case 32:
- e.preventDefault();
- seat.click();
- break;
- //UP & DOWN
- case 40:
- case 38:
- e.preventDefault();
- /*
- * This is a recursive, immediate function which searches for the first "focusable" row.
- *
- * We're using immediate function because we want a convenient access to some DOM elements
- * We're using recursion because sometimes we may hit an empty space rather than a seat.
- *
- */
- $newSeat = (function findAvailable($rows, $seats, $currentRow) {
- var $newRow;
- //let's determine which row should we move to
- if (!$rows.index($currentRow) && e.which == 38) {
- //if this is the first row and user has pressed up arrow, move to the last row
- $newRow = $rows.last();
- } else if ($rows.index($currentRow) == $rows.length-1 && e.which == 40) {
- //if this is the last row and user has pressed down arrow, move to the first row
- $newRow = $rows.first();
- } else {
- //using eq to get an element at the desired index position
- $newRow = $rows.eq(
- //if up arrow, then decrement the index, if down increment it
- $rows.index($currentRow) + (e.which == 38 ? (-1) : (+1))
- );
- }
- //now that we know the row, let's get the seat using the current column position
- $newSeat = $newRow.find('.seatCharts-seat,.seatCharts-space').eq($seats.index($seat));
- //if the seat we found is a space, keep looking further
- return $newSeat.hasClass('seatCharts-space') ?
- findAvailable($rows, $seats, $newRow) : $newSeat;
- })($seat
- //get a reference to the parent container and then select all rows but the header
- .parents('.seatCharts-container')
- .find('.seatCharts-row:not(.seatCharts-header)'),
- $seat
- //get a reference to the parent row and then find all seat cells (both seats & spaces)
- .parents('.seatCharts-row:first')
- .find('.seatCharts-seat,.seatCharts-space'),
- //get a reference to the current row
- $seat.parents('.seatCharts-row:not(.seatCharts-header)')
- );
- //we couldn't determine the new seat, so we better give up
- if (!$newSeat.length) {
- return;
- }
- //remove focus from the old seat and put it on the new one
- seat.blur();
- seats[$newSeat.attr('id')].focus();
- $newSeat.focus();
- //update our "aria" reference with the new seat id
- seatCharts.attr('aria-activedescendant', $newSeat.attr('id'));
- break;
- //LEFT & RIGHT
- case 37:
- case 39:
- e.preventDefault();
- /*
- * The logic here is slightly different from the one for up/down arrows.
- * User will be able to browse the whole map using just left/right arrow, because
- * it will move to the next row when we reach the right/left-most seat.
- */
- $newSeat = (function($seats) {
- if (!$seats.index($seat) && e.which == 37) {
- //user has pressed left arrow and we're currently on the left-most seat
- return $seats.last();
- } else if ($seats.index($seat) == $seats.length -1 && e.which == 39) {
- //user has pressed right arrow and we're currently on the right-most seat
- return $seats.first();
- } else {
- //simply move one seat left or right depending on the key
- return $seats.eq($seats.index($seat) + (e.which == 37 ? (-1) : (+1)));
- }
- })($seat
- .parents('.seatCharts-container:first')
- .find('.seatCharts-seat:not(.seatCharts-space)'));
- if (!$newSeat.length) {
- return;
- }
- //handle focus
- seat.blur();
- seats[$newSeat.attr('id')].focus();
- $newSeat.focus();
- //update our "aria" reference with the new seat id
- seatCharts.attr('aria-activedescendant', $newSeat.attr('id'));
- break;
- default:
- break;
- }
- };
- })(fn, fn.node()));
- //.appendTo(seatCharts.find('.' + row));
- }
- })(fn, settings);
- fn.addClass('seatCharts-container');
- //true -> deep copy!
- $.extend(true, settings, setup);
- //Generate default row ids unless user passed his own
- settings.naming.rows = settings.naming.rows || (function(length) {
- var rows = [];
- for (var i = 1; i <= length; i++) {
- rows.push(i);
- }
- return rows;
- })(settings.map.length);
- //Generate default column ids unless user passed his own
- settings.naming.columns = settings.naming.columns || (function(length) {
- var columns = [];
- for (var i = 1; i <= length; i++) {
- columns.push("0"+i);
- }
- return columns;
- })(settings.map[0].split('').length);
- if (settings.naming.top) {
- var $headerRow = $('<div></div>')
- .addClass('seatCharts-row seatCharts-header');
- if (settings.naming.left) {
- $headerRow.append($('<div></div>').addClass('seatCharts-cell'));
- }
- $.each(settings.naming.columns, function(index, value) {
- $headerRow.append(
- $('<div></div>')
- .addClass('seatCharts-cell')
- .text(value)
- );
- });
- }
- fn.append($headerRow);
- //do this for each map row
- $.each(settings.map, function(row, characters) {
- var $row = $('<div></div>').addClass('seatCharts-row');
- if (settings.naming.left) {
- $row.append(
- $('<div></div>')
- .addClass('seatCharts-cell seatCharts-space')
- .text(settings.naming.rows[row])
- );
- }
- /*
- * Do this for each seat (letter)
- *
- * Now users will be able to pass custom ID and label which overwrite the one that seat would be assigned by getId and
- * getLabel
- *
- * New format is like this:
- * a[ID,label]a[ID]aaaaa
- *
- * So you can overwrite the ID or label (or both) even for just one seat.
- * Basically ID should be first, so if you want to overwrite just label write it as follows:
- * a[,LABEL]
- *
- * Allowed characters in IDs areL 0-9, a-z, A-Z, _
- * Allowed characters in labels are: 0-9, a-z, A-Z, _, ' ' (space)
- *
- */
- $.each(characters.match(/[a-z_]{1}()?/gi), function (column, characterParams) {
[0−9a−z]0,(,[0−9a−z]+)? - var matches = characterParams.match(/([a-z_]{1})()?/i),
([0−9a−z,]+) - //no matter if user specifies [] params, the character should be in the second element
- character = matches[1],
- //check if user has passed some additional params to override id or label
- params = typeof matches[3] !== 'undefined' ? matches[3].split(',') : [],
- //id param should be first
- overrideId = params.length ? params[0] : null,
- //label param should be second
- overrideLabel = params.length === 2 ? params[1] : null;
- $row.append(character != '_' ?
- //if the character is not an underscore (empty space)
- (function(naming) {
- //console.log(naming);
- //so users don't have to specify empty objects
- // console.log(naming);
- // console.log("character"+naming.getLabel(character, naming.rows[row], naming.columns[column]));
- // console.log("row"+row);
- // console.log(column);
- // console.log(naming.data)
- settings.seats[character] = character in settings.seats ? settings.seats[character] : {};
- var id = overrideId ? overrideId : naming.getId(character, naming.rows[row], naming.columns[column]);
- seats[id] = new seat({
- id : id,
- label : naming.data[row][column] ,
- // label : overrideLabel ? overrideLabel : naming.getLabel(character, naming.rows[row], naming.columns[column]),
- row : row,
- column : column,
- character : character
- });
- seatIds.push(id);
- return seats[id].node();
- })(settings.naming) :
- //this is just an empty space (_)
- $('<div></div>').addClass('seatCharts-cell seatCharts-space')
- );
- });
- fn.append($row);
- });
- //if there're any legend items to be rendered
- settings.legend.items.length ? (function(legend) {
- //either use user-defined container or create our own and insert it right after the seat chart div
- var $container = (legend.node || $('<div></div').insertAfter(fn))
- .addClass('seatCharts-legend');
- var $ul = $('<ul></ul>')
- .addClass('seatCharts-legendList')
- .appendTo($container);
- $.each(legend.items, function(index, item) {
- $ul.append(
- $('<li></li>')
- .addClass('seatCharts-legendItem')
- .append(
- $('<div></div>')
- //merge user defined classes with our standard ones
- .addClass(['seatCharts-seat', 'seatCharts-cell', item[1]].concat(
- settings.classes,
- typeof settings.seats[item[0]] == "undefined" ? [] : settings.seats[item[0]].classes).join(' ')
- )
- )
- .append(
- $('<span></span>')
- .addClass('seatCharts-legendDescription')
- .text(item[2])
- )
- );
- });
- return $container;
- })(settings.legend) : null;
- fn.attr({
- tabIndex : 0
- });
- //when container's focused, move focus to the first seat
- fn.focus(function() {
- if (fn.attr('aria-activedescendant')) {
- seats[fn.attr('aria-activedescendant')].blur();
- }
- fn.find('.seatCharts-seat:not(.seatCharts-space):first').focus();
- seats[seatIds[0]].focus();
- });
- //public methods of seatCharts
- fn.data('seatCharts', {
- seats : seats,
- seatIds : seatIds,
- //set for one, set for many, get for one
- status: function() {
- var fn = this;
- return arguments.length == 1 ? fn.seats[arguments[0]].status() : (function(seatsIds, newStatus) {
- return typeof seatsIds == 'string' ? fn.seats[seatsIds].status(newStatus) : (function() {
- $.each(seatsIds, function(index, seatId) {
- fn.seats[seatId].status(newStatus);
- });
- })();
- })(arguments[0], arguments[1]);
- },
- each : function(callback) {
- var fn = this;
- for (var seatId in fn.seats) {
- if (false === callback.call(fn.seats[seatId], seatId)) {
- return seatId;//return last checked
- }
- }
- return true;
- },
- node : function() {
- var fn = this;
- //basically create a CSS query to get all seats by their DOM ids
- return $('#' + fn.seatIds.join(',#'));
- },
- find : function(query) {//D, a.available, unavailable
- var fn = this;
- var seatSet = fn.set();
- //user searches just for a particual character
- return query.length == 1 ? (function(character) {
- fn.each(function() {
- if (this.char() == character) {
- seatSet.push(this.settings.id, this);
- }
- });
- return seatSet;
- })(query) : (function() {
- //user runs a more sophisticated query, so let's see if there's a dot
- return query.indexOf('.') > -1 ? (function() {
- //there's a dot which separates character and the status
- var parts = query.split('.');
- fn.each(function(seatId) {
- if (this.char() == parts[0] && this.status() == parts[1]) {
- seatSet.push(this.settings.id, this);
- }
- });
- return seatSet;
- })() : (function() {
- fn.each(function() {
- if (this.status() == query) {
- seatSet.push(this.settings.id, this);
- }
- });
- return seatSet;
- })();
- })();
- },
- set : function set() {//inherits some methods
- var fn = this;
- return {
- seats : [],
- seatIds : [],
- length : 0,
- status : function() {
- var args = arguments,
- that = this;
- //if there's just one seat in the set and user didn't pass any params, return current status
- return this.length == 1 && args.length == 0 ? this.seats[0].status() : (function() {
- //otherwise call status function for each of the seats in the set
- $.each(that.seats, function() {
- this.status.apply(this, args);
- });
- })();
- },
- node : function() {
- return fn.node.call(this);
- },
- each : function() {
- return fn.each.call(this, arguments[0]);
- },
- get : function() {
- return fn.get.call(this, arguments[0]);
- },
- find : function() {
- return fn.find.call(this, arguments[0]);
- },
- set : function() {
- return set.call(fn);
- },
- push : function(id, seat) {
- this.seats.push(seat);
- this.seatIds.push(id);
- ++this.length;
- }
- };
- },
- //get one object or a set of objects
- get : function(seatsIds) {
- var fn = this;
- return typeof seatsIds == 'string' ?
- fn.seats[seatsIds] : (function() {
- var seatSet = fn.set();
- $.each(seatsIds, function(index, seatId) {
- if (typeof fn.seats[seatId] === 'object') {
- seatSet.push(seatId, fn.seats[seatId]);
- }
- });
- return seatSet;
- })();
- },
- dataReload : function(data){
- // console.log(this)
- // console.log(data);
- }
- });
- return fn.data('seatCharts');
- }
- })(jQuery);
阅读全文
0 0
- jquery-seat-charts 使用-自定义座位号 及 重新加载数据
- jquery-seat-charts 使用-自定义座位号 及 重新加载数据
- jquery.seat-charts选座
- jquery-seat-charts 使用(去除第一个元素获取焦点)
- Jquery datatables 重新加载数据
- JQuery easyui datagrid重新加载数据
- jquery 使用math.random重新加载图片
- jquery.seat-chartsMark在线选座插件使用
- Jquery 加载数据及请求数据方式
- jqGrid - 重新加载数据
- jqgrid 重新加载数据.
- 怎么重新加载(刷新)页面使用jquery
- jquery combobox下拉及异步加载数据
- 【jQuery】使用ajax()方法加载服务器数据
- TableDataSource 表格数据重新加载
- EasyUi datagrid重新加载数据
- jqGrid之重新加载数据
- jqgrid treegrid 重新加载数据
- 1月课程表|线下实战演练,快速提升你的运营能力
- Bootstrap-table的使用及如何给单元格添加功能按钮和事件等操作!
- Mybatis分页插件PageHelper
- FK安卓-1-开机流程
- numpy的unwrap函数
- jquery-seat-charts 使用-自定义座位号 及 重新加载数据
- 句柄
- 2018年用户体验设计趋势
- 新零售新模式:完整了解「快闪店」运作
- 备战2018|春招or跳槽?大学生和职场新人最后的机会!
- 【七月Python入门】 第二课关键字及循环控制
- Java中 VO、 PO、DO、DTO、 BO、 QO、DAO、POJO的概念
- 3个方法,教你激起用户的渴望
- Shell编程详解