javascript实现表格排序 编辑 拖拽 缩放


Posted in Javascript onJanuary 02, 2015

简单表格排序

 可以双击编辑 自定义编辑后的 规则

 可拖动列进行列替换

 可推动边框进行列宽度的缩放

 

 <!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=gb2312" />

<title>Table</title>

</head>

<style type="text/css">

body{ font-size:12px}

#tab{ border-collapse: collapse;}

.edit{ height:16px; width:98%; background-color:#EFF7FF; font-size:12px; border:0px;}

#tab thead td{ background:url(http://images.cnblogs.com/cnblogs_com/wtcsy/192373/r_t.bmp);color:#183C94;word-break:break-all}

#tab tbody td{overflow:hidden;word-break:break-all;}

#tab td{border: 1px solid #CECFCE;height:20px;line-height:20px;vertical-align:middle; }

#tab td.tc{text-align:center;}

.div{width:10px;height:6px; border:1px solid #999999; background-color:#FFFFFF; position:absolute; display:none;}

.line{ width:2px; background-color:#999999;  position:absolute; display:none}

.dr{height:100%;width:2px;background:#CECFCE;float:right;margin-right:-1px;cursor:sw-resize}

.r{float:right;}

.l{float:left;}

#tab thead td.thover{ background-image:url(http://album.hi.csdn.net/app_uploads/wtcsy/20081126/000054336.p.gif);background-repeat:repeat-x;}

</style>

<body >

<table id="tab"  border="0" cellspacing="1" cellpadding="0">

 <thead>

   <tr>

       <td width="80"class="tc" ><span class="l">ID</span><div class="r dr"></div></td>

       <td width="80"class="tc"><span class="l">选中</span><div class="r dr"></div></td>

       <td  width="130" class="tc"><span class="l">姓名</span><div class="r dr"></div></td>

       <td width="130" class="tc" ><span class="l">生日</span><div class="r dr"></div></td>

       <td width="220" class="tc" ><span class="l">备注</span><div class="r dr"></div></td>

   </tr>

  </thead>

  <tbody>

  <tr>

    <td height="16">1</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>小三</td>

    <td>1982-05-27</td>

    <td>杯具,全是杯具</td>

  </tr>

  <tr>

    <td>3</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>李四</td>

    <td>1983-06-27</td>

    <td>恩恩我魔兽技术不错</td>    

  </tr>

  <tr>

    <td>2</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>王五</td>

    <td>1987-05-27</td>

    <td>波斯王子 时之刃还不错</td>    

  </tr>

  <tr>

    <td>4</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>赵六</td>

    <td>1988-05-27</td>

    <td>我叫赵六</td>    

  </tr>

  <tr>

    <td>5</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>朱八</td>

    <td>1984-05-27</td>

    <td>洗洗睡吧</td>    

  </tr>

  <tr>

    <td>6</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>阿斯多夫</td>

    <td>1984-06-27</td>

    <td>阿斯多夫暗室逢灯</td>    

  </tr>

  <tr>

    <td>7</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>杯具</td>

    <td>1984-06-27</td>

    <td>很多的杯具</td>    

  </tr>

  <tr>

    <td>8</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>餐具</td>

    <td>1984-02-27</td>

    <td>很多的餐具</td>    

  </tr>

  <tr>

    <td>8</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>洗具</td>

    <td>1984-08-27</td>

    <td>很多的洗具</td>    

  </tr> 

  <tr>

    <td>9</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>内牛满面</td>

    <td>1984-12-27</td>

    <td>10快一晚</td>    

  </tr>

  <tr>

    <td>10</td>

    <td><input type ="checkbox"><input name="ss" type="radio"  /></td>

    <td>犀利哥</td>

    <td>1984-12-21</td>

    <td>嘿嘿</td>    

  </tr>                        

  </tbody>

</table>

<script language="javascript">

(function(window,undefined){

window.Sys = function (ua){

    var b = {

        ie: /msie/.test(ua) && !/opera/.test(ua),

        opera: /opera/.test(ua),

        safari: /webkit/.test(ua) && !/chrome/.test(ua),

        firefox: /firefox/.test(ua),

        chrome: /chrome/.test(ua)

    },vMark = "";

    for (var i in b) {

        if (b[i]) { vMark = "safari" == i ? "version" : i; break; }

    }

    b.version = vMark && RegExp("(?:" + vMark + ")[\\/: ]([\\d.]+)").test(ua) ? RegExp.$1 : "0";

    b.ie6 = b.ie && parseInt(b.version, 10) == 6;

    b.ie7 = b.ie && parseInt(b.version, 10) == 7;

    b.ie8 = b.ie && parseInt(b.version, 10) == 8;   

    return b;

}(window.navigator.userAgent.toLowerCase());
window.Sys.ie6&&document.execCommand("BackgroundImageCache", false, true);
window.$ = function(Id){

    return document.getElementById(Id);

};

window.addListener = function(element,e,fn){

    !element.events&&(element.events = {});

    element.events[e]&&(element.events[e][addListener.guid++]=fn)||(element.events[e] = {'0':fn});

    element.addEventListener?element.addEventListener(e,fn,false):element.attachEvent("on" + e,fn);

};

window.addListener.guid = 1;

window.removeListener = function(element,e,fn){

    var handlers = element.events[e],type;

    if(fn){

        for(type in handlers)

            if(handlers[type]===fn){

                element.removeEventListener?element.removeEventListener(e,fn,false):element.detachEvent("on" + e,fn);

                delete handlers[type];

            }

    }else{

        for(type in handlers){

            element.removeEventListener?element.removeEventListener(e,handlers[type],false):element.detachEvent("on" + e,handlers[type]);

            delete handlers[type];

        }

    }        

};

window.setStyle = function(e,o){

    if(typeof o=="string")

        e.style.cssText=o;

    else    

        for(var i in o)

            e.style[i] = o[i];

};
var slice = Array.prototype.slice;

window.Bind = function(object, fun) {

    var args = slice.call(arguments).slice(2);

    return function() {

            return fun.apply(object, args);

    };

};

window.BindAsEventListener = function(object, fun,args) {

    var args = slice.call(arguments).slice(2);

    return function(event) {

        return fun.apply(object, [event || window.event].concat(args));

    }

};

//copy from jQ

window.Extend = function(){

 var target = arguments[0] || {}, i = 1, length = arguments.length, deep = true, options;

 if ( typeof target === "boolean" ) {

  deep = target;

  target = arguments[1] || {};

  i = 2;

 }

 if ( typeof target !== "object" && Object.prototype.toString.call(target)!="[object Function]")

  target = {};

 for(;i<length;i++){

  if ( (options = arguments[ i ]) != null )

   for(var name in options){

    var src = target[ name ], copy = options[ name ];

    if ( target === copy )

     continue;

    if ( deep && copy && typeof copy === "object" && !copy.nodeType ){

     target[ name ] = arguments.callee( deep, src || ( copy.length != null ? [ ] : { } ), copy );

    } 

    else if(copy !== undefined)

     target[ name ] = copy;      

   }

 }

 return target;   

};

window.objPos = function(o){

 var x = 0, y = 0;

 do{x += o.offsetLeft;y += o.offsetTop;}while((o=o.offsetParent));

 return {'x':x,'y':y};

}

window.Class = function(properties){

    var _class = function(){return (arguments[0] !== null && this.initialize && typeof(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;};

    _class.prototype = properties;

    return _class;

};

window.hasClass  = function(element, className){ 

 return element.className.match(new RegExp('(\\s|^)'+className+'(\\s|$)')); 

} ;

window.addClass  = function(element, className) { 

 !this.hasClass(element, className)&&(element.className += " "+className);

} 

window.removeClass = function(element, className) { 

 hasClass(element, className)&&(element.className = element.className.replace(new RegExp('(\\s|^)'+className+'(\\s|$)'),' ')); 

} 

})(window);
var Table = new Class({

    options :{

        minWidth : 62

    },

    initialize : function(tab,set){

        this.table      = tab;

        this.rows       = [];             //里面记录所有tr的引用

        this.sortCol    = null;           //记录哪列正在排序中

        this.inputtd    = null;           //记录哪个td正在被编辑了

        this.editconfig = {};             //编辑表格的规则和提示

        this.thead      = tab.getElementsByTagName('thead')[0];

        this.theadTds   = tab.getElementsByTagName('thead')[0].getElementsByTagName('td'); //常常用到的dom集合可以用个属性来引用

        this.tbodyTds   = tab.getElementsByTagName('tbody')[0].getElementsByTagName('td');

        this.closConfig = {

   on    : false,

            td    : null,

            totd  : null

        };

  this.widthConfig = {

   td          : null,

   nexttd      : null,

   x           : 0,

   tdwidth     : 0,

   nexttdwidth : 0

  };

  Extend(this,this.options);

  //不知道原因 反正不设置就会乱跳

  (Sys.ie6||Sys.chrome)&&(tab.width=tab.offsetWidth)

         //记录那些checkbox,radio被选中了   ie6在做dom操作的时候不会记住这些状态

        if(Sys.ie6){

            this.checkbox = {};          

            var checkboxs = tab.getElementsByTagName('input'),i=0,l=checkboxs.length;

            for(;i<l;i++)

                (checkboxs[i].type=="checkbox"||checkboxs[i].type=="radio")&&

                addListener(checkboxs[i],"click",Bind(this,function(elm,i){

                    elm.checked==true?(this.checkbox[i] = elm):(delete this.checkbox[i]);

                },checkboxs[i],i));        

        };

        var i=0,l=set.length,rows =tab.tBodies[0].rows,d=document,tabTads=tab.getElementsByTagName('td'),length=this.theadTds.length;

        //编辑用的input

  this.input = d.createElement('input');  

        this.input.type = "text";

        this.input.className = 'edit';

        //用于显示正在拖拽的div

        this.div = d.body.appendChild(d.createElement('div'));

        this.div.className ="div";

  //进行缩放的时候显示的竖线

  this.line = d.body.appendChild(d.createElement('div'));

  this.line.className = 'line';

  this.line.style.top = objPos(tab).y +"px";

  //遍历set 做一些设置                           

        for(;i<l;i++){

            //给需要排序的猎头绑定事件

            addListener(this.theadTds[set[i].id],'click',Bind(this,this.sortTable,this.theadTds[set[i].id],set[i].type));

            //给需要编辑的表给列定义所需配置

            set[i].edit&&(this.editconfig[set[i].id]={rule:set[i].edit.rule,message:set[i].edit.message});

        }

        //把 所有的tr放到一个数组 用于排序    

        for( i=0,l=rows.length;i<l;i++)

            this.rows[i]=rows[i];

         

                   //遍历所有的td 做一些设置     

        for( i=0,l=tabTads.length;i<l;i++){

            //将头部的td全部做上标记 拖拽的时候要用到

            i<length&&tabTads[i].setAttribute('clos',i);

            //将需要编辑的td添加edit属性

            i>=length&&this.editconfig[i%length]&&tabTads[i].setAttribute('edit',i%length);

        }

        

        //绑定 拖拽 和缩放的操作

        addListener(this.thead,'mousedown',BindAsEventListener(this,this.dragOrWidth));

        

        //拖拽的时候 记录移动到了那列td上

        addListener(this.thead,'mouseover',BindAsEventListener(this,this.theadHover));

  

  //唉

  addListener(this.thead,'mouseout',BindAsEventListener(this,this.theadOut));

        

        //绑定编辑事件 根据e.srcElement or e.target去判断是哪个表格被编辑    

        addListener(tab,'dblclick',BindAsEventListener(this,this.edit));    

        

        //当离开input时候保存下修改的内容

        addListener(this.input,'blur',Bind(this,this.save,this.input));                  

    },

    sortTable :function(td,type){ //td为点击的那个元素 n 为哪一列进行排序 type为进行什么类型的排序

        var frag=document.createDocumentFragment(),span=td.getElementsByTagName('span')[0],str= span.innerHTML;

        if(td===this.sortCol){

            this.rows.reverse();

            span.innerHTML =str.replace(/.$/,str.charAt(str.length-1)=="↓"?"↑":"↓") ;

        }else{

            this.rows.sort(this.compare(td.getAttribute('clos'),type));

            span.innerHTML = span.innerHTML + "↑";

     this.sortCol!=null&&(this.sortCol.getElementsByTagName('span')[0].innerHTML = this.sortCol.getElementsByTagName('span')[0].innerHTML.replace(/.$/,''));//把之前那列排序的标识去掉

        };

        for(var i=0,l=this.rows.length;i<l;i++)

            frag.appendChild(this.rows[i]);

        this.table.tBodies[0].appendChild(frag);

        if(Sys.ie6){

            for(var s in this.checkbox)

                this.checkbox[s].checked = true;

        }

        this.sortCol = td;   //记录哪一列正在排序中          

    },

    compare :function(n,type){

  return function (a1,a2){

   var convert ={

    int    : function(v){return parseInt(v)},

    float  : function(v){return parseFloat(v)},

    date   : function(v){return v.toString()},

    string : function(v){return v.toString()}

   };

   !convert[type]&&(convert[type]=function(v){return v.toString()});

   a1 =convert[type](a1.cells[n].innerHTML);

   a2 =convert[type](a2.cells[n].innerHTML);

   return a1==a2?0:a1<a2?-1:1;           

  };

    },

    edit: function(e){

        var elem = this.inputtd=e.srcElement || e.target;

        if(!elem.getAttribute('edit'))return;

        this.input.value = elem.innerHTML;

        elem.innerHTML = "";

        elem.appendChild(this.input);

        this.input.focus();

    },

    save : function(elem){

  var editinfo=this.editconfig[elem.parentNode.getAttribute('edit')],status={

   "[object Function]" : 'length' in editinfo.rule&&editinfo.rule(this.input.value)||false,        

   "[object RegExp]"   : 'test' in editinfo.rule&&editinfo.rule.test(this.input.value)||false

  }[Object.prototype.toString.call(editinfo.rule)],_self=this;

  //如果不符合条件  修改提示信息

  typeof status != "boolean"&&(editinfo.message = status);

  if(status===true){

   this.inputtd.innerHTML = this.input.value;

   this.inputtd=null;

  }else{

   alert(editinfo.message);

   //firefox下  直接用input.focus()不会执行  用setTimeout可以执行

   setTimeout(function(){_self.input.focus()},0);

  }                     

    },

    theadHover  : function(e){

        var elem = e.srcElement || e.target;

        if(elem.nodeName.toLowerCase() ==='td'&&this.closConfig.on){

            this.closConfig.totd = elem.getAttribute('clos');

   !hasClass(elem,'thover')&&addClass(elem,'thover');

  }         

    },

 theadOut : function(e){

        var elem = e.srcElement || e.target;

        if(elem.nodeName.toLowerCase() ==='td'&&this.closConfig.on)removeClass(elem,'thover')

 },

    dragOrWidth : function(e){

        var elem = e.srcElement || e.target,widthConfig=this.widthConfig;

        

        //执行拖拽

        if(elem.nodeName.toLowerCase()==='td'){

            this.closConfig.td = elem.getAttribute('clos');

            addListener(document,'mousemove',BindAsEventListener(this,this.dragMove));

            addListener(document,'mouseup',Bind(this,this.dragUp));

   this.closConfig.on = true;

   Sys.ie?this.thead.setCapture(false):e.preventDefault();

        }

                   

  //执行宽度缩放

  if(elem.nodeName.toLowerCase()==='div'){

   Sys.ie?(e.cancelBubble=true):e.stopPropagation();

   //如果是最后一个td里面的div 不进行缩放

   if(this.theadTds[this.theadTds.length-1]===elem.parentNode)return

   Sys.ie?this.thead.setCapture(false):e.preventDefault();

   widthConfig.x = e.clientX;

   widthConfig.td = elem.parentNode;

   widthConfig.nexttd = widthConfig.td.nextSibling;

   while(widthConfig.nexttd.nodeName.toLowerCase()!="td"){

     widthConfig.nexttd = widthConfig.nexttd.nextSibling;

   };

   widthConfig.tdwidth     = widthConfig.td.offsetWidth;

   widthConfig.nexttdwidth = widthConfig.nexttd.offsetWidth;

   this.line.style.height  = this.table.offsetHeight +"px";

   addListener(document,'mousemove',BindAsEventListener(this,this.widthMove));

   addListener(document,'mouseup',Bind(this,this.widthUp));                                                

  }

    },

    dragMove : function(e){

        window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

        setStyle(this.div,{display:"block",left:e.clientX+9+"px",top:e.clientY+20+"px"});

    },

    dragUp :function(){

        var closConfig = this.closConfig,rows = this.table.getElementsByTagName('tr'),td,n,o,i=0,l=rows.length;

  this.div.style.display = "none";

        removeListener(document,'mousemove');

        removeListener(document,'mouseup');

  Sys.ie&&this.thead.releaseCapture();

  closConfig.on = false; 

  if(closConfig.totd===null)return;

  removeClass(this.theadTds[closConfig.totd],'thover');

        //在同一列 不进行列替换

        if(closConfig.td === closConfig.totd)return;

  

  //进行列替换 如果

  if(closConfig.td*1+1===closConfig.totd*1){

   n = closConfig.totd;

   o = closConfig.td;

  }else{

   n = closConfig.td;

   o = closConfig.totd;

  }

        for(;i<l;i++){

            td = rows[i].getElementsByTagName('td');

            rows[i].insertBefore(td[n],td[o]);

        }                 

                   

        //重新标识表头

        for(i=0,l=this.theadTds.length;i<l;i++)

            this.theadTds[i].setAttribute('clos',i);

  closConfig.totd=closConfig.td=null;      

    },

 widthMove : function(e){

  window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

  var widthConfig = this.widthConfig,x = e.clientX - widthConfig.x,left = e.clientX,clientX=left;

  if(clientX<widthConfig.x&&widthConfig.x - clientX>widthConfig.tdwidth-this.minWidth){

   left = widthConfig.x - widthConfig.tdwidth+this.minWidth;

  }

  if(clientX>widthConfig.x&&clientX - widthConfig.x>widthConfig.nexttdwidth-this.minWidth){

   left =widthConfig.x + widthConfig.nexttdwidth-this.minWidth;        

  }

  setStyle(this.line,{display:"block",left:left+"px"});    

 },

 widthUp : function(){

  this.line.style.display = "none";

  var widthConfig = this.widthConfig,x= parseInt(this.line.style.left) - widthConfig.x;  

  widthConfig.nexttd.style.width = widthConfig.nexttdwidth -x -1 +'px';

  widthConfig.td.style.width = widthConfig.tdwidth + x -1 +'px';

  Sys.ie&&this.thead.releaseCapture();

  removeListener(document,'mousemove');

  removeListener(document,'mouseup');

 }            

});

window.onload = function(){

    function checkName(val){

        if(val.replace(/^\s+$/g,'')==='') return '姓名输入不能为空';

        if(val.replace(/^\s+|\s+$/,'').length>10) return '姓名长度不能大于10个字符';

        if(!/^[\u4e00-\u9fa5a-z]+$/i.test(val)) return '姓名只能输入中文或者是字母';

        return true;

    };

 function checkRemark(val){

  if(val.replace(/^\s+$/g,'')==='') return '备注输入不能为空';

  if(val.replace(/^\s+|\s+$/,'').length>15) return '备注长度不能大于15个字符';

  if(!/^[\u4e00-\u9fa5\w\s]+$/i.test(val)) return '备注只能输入中文数字下划线空格';

  return true;

 }

    var set = [

        {id:0,type:"int"},

        {id:2,type:"string",edit:{rule:checkName,message:''}},

        {id:3,type:"date",edit:{rule:/^\d{4}\-\d{2}\-\d{2}$/,message:"按这中格式输入日期 1985-02-30"}},

        {id:4,type:"string",edit:{rule:checkRemark,message:''}}

    ];

    new Table($("tab"),set);

}

</script>

</body>

</html>

 

 已知BUG:

 ie6下 中文不自动换行

 非ie下字母和数字也不自动换行确实让人恼火

 chrome浏览器下点击运行好像问题很大  拿到本地测试会比较好

Javascript 相关文章推荐
再谈querySelector和querySelectorAll的区别与联系
Apr 20 Javascript
jquery选择器简述
Aug 31 Javascript
jQuery多文件异步上传带进度条实例代码
Aug 16 Javascript
javascript显示系统当前时间代码
Dec 29 Javascript
JS中静态页面实现微信分享功能
Feb 06 Javascript
js实现带简单弹性运动的导航条
Feb 22 Javascript
jquery中$.fn和图片滚动效果实现的必备知识总结
Apr 21 jQuery
js实现城市级联菜单的2种方法
Jun 23 Javascript
基于Vue实现电商SKU组合算法问题
May 29 Javascript
Vue+Element实现网页版个人简历系统(推荐)
Dec 31 Javascript
vue中activated的用法
Jan 03 Vue.js
vue使用节流函数的踩坑实例指南
May 20 Vue.js
原生javascript实现DIV拖拽并计算重复面积
Jan 02 #Javascript
javascript使用smipleChart实现简单图表
Jan 02 #Javascript
原生javascript实现简单的datagrid数据表格
Jan 02 #Javascript
浅谈jQuery事件绑定原理
Jan 02 #Javascript
js+jquery实现图片裁剪功能
Jan 02 #Javascript
javascript 构造函数方式定义对象
Jan 02 #Javascript
深入探寻javascript定时器
Jan 02 #Javascript
You might like
php实现的美国50个州选择列表实例
2015/04/20 PHP
php实现比较两个文件夹异同的方法
2015/06/18 PHP
php判断当前操作系统类型
2015/10/28 PHP
golang与php实现计算两个经纬度之间距离的方法
2016/07/22 PHP
PHP Ajax JavaScript Json获取天气信息实现代码
2016/08/17 PHP
php实现记事本案例
2020/10/20 PHP
jQuery实现鼠标单击网页文字后在文本框显示的方法
2015/05/06 Javascript
javascript实现下拉提示选择框
2015/12/29 Javascript
原生javascript实现的一个简单动画效果
2016/03/30 Javascript
jQueryeasyui 中如何使用datetimebox 取两个日期间相隔的天数
2017/06/13 jQuery
jQuery实现的文字逐行向上间歇滚动效果示例
2017/09/06 jQuery
JavaScript中的ES6 Proxy的具体使用
2019/06/16 Javascript
解决layer.open后laydate失效的问题
2019/09/06 Javascript
JavaScript判断浏览器版本的方法
2019/11/03 Javascript
[01:32]完美世界DOTA2联赛10月29日精彩集锦
2020/10/30 DOTA
[45:44]完美世界DOTA2联赛PWL S2 FTD vs PXG 第一场 11.27
2020/12/01 DOTA
介绍Python的Django框架中的静态资源管理器django-pipeline
2015/04/25 Python
开始着手第一个Django项目
2015/07/15 Python
完美解决python遍历删除字典里值为空的元素报错问题
2016/09/11 Python
详解python3中zipfile模块用法
2018/06/18 Python
对numpy Array [: ,] 的取值方法详解
2018/07/02 Python
PyQt5+requests实现车票查询工具
2019/01/21 Python
对python 自定义协议的方法详解
2019/02/13 Python
Django使用Channels实现WebSocket的方法
2019/07/28 Python
python tkinter库实现气泡屏保和锁屏
2019/07/29 Python
python实现美团订单推送到测试环境,提供便利操作示例
2019/08/09 Python
python将邻接矩阵输出成图的实现
2019/11/21 Python
Python爬虫教程之利用正则表达式匹配网页内容
2020/12/08 Python
台湾良兴购物网:EcLife
2019/12/01 全球购物
企业演讲稿范文
2013/12/28 职场文书
高中考试作弊检讨书
2014/01/14 职场文书
企业办公室岗位职责
2014/03/12 职场文书
大学理论知识学习自我鉴定
2014/04/28 职场文书
关于调整工作时间的通知
2015/04/24 职场文书
Java用自带的Image IO给图片添加水印
2021/06/15 Java/Android
画错魏国疆域啦!《派对咖孔明》动画因作画失误于官网致歉
2022/04/07 日漫