Browse Source

后台功能重写。

xian 5 years ago
parent
commit
ec85b1e737
40 changed files with 54155 additions and 0 deletions
  1. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/Uploader.swf
  2. 778 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/cropper/cropper.js
  3. 26 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/cropper/index.html
  4. 268 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/cropper/uploader.js
  5. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/expressInstall.swf
  6. 29 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/image-upload/index.html
  7. 573 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/image-upload/upload.js
  8. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/Thumbs.db
  9. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/bg.png
  10. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/icons.png
  11. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/icons.psd
  12. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/image.png
  13. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/progress.png
  14. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/progress.psd
  15. BIN
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/success.png
  16. 20 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/md5-demo/index.html
  17. 57 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/md5-demo/script.js
  18. 430 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/requirejs/app.js
  19. 37 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/requirejs/index.html
  20. 36 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/requirejs/require.js
  21. 4 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/server/crossdomain.xml
  22. 177 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/server/fileupload.php
  23. 172 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/server/fileupload2.php
  24. 63 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/server/preview.php
  25. 95 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.css
  26. 6502 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.custom.js
  27. 2 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.custom.min.js
  28. 8083 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.fis.js
  29. 4622 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.flashonly.js
  30. 2 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.flashonly.min.js
  31. 6030 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.html5only.js
  32. 2 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.html5only.min.js
  33. 8106 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.js
  34. 3 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.min.js
  35. 5026 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.noimage.js
  36. 2 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.noimage.min.js
  37. 8012 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.nolog.js
  38. 3 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.nolog.min.js
  39. 4993 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.withoutimage.js
  40. 2 0
      watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.withoutimage.min.js

BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/Uploader.swf


+ 778 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/cropper/cropper.js

@@ -0,0 +1,778 @@
+/*!
+ * Cropper v0.3.2
+ * https://github.com/fengyuanchen/cropper
+ *
+ * Copyright 2014 Fengyuan Chen
+ * Released under the MIT license
+ */
+
+(function(factory) {
+    if (typeof define === "function" && define.amd) {
+        // AMD. Register as anonymous module.
+        define(["jquery"], factory);
+    } else {
+        // Browser globals.
+        factory(jQuery);
+    }
+}(function($) {
+
+    "use strict";
+
+    var $window = $(window),
+        Cropper = function(element, options) {
+            options = $.isPlainObject(options) ? options : {};
+            this.$image = $(element);
+            this.defaults = $.extend({}, Cropper.defaults, this.$image.data(), options);
+            this.init();
+        };
+
+    Cropper.prototype = {
+        construstor: Cropper,
+
+        init: function() {
+            this.setAspectRatio(this.defaults.aspectRatio);
+            this.render();
+        },
+
+        render: function(callback) {
+            var that = this,
+                $image = this.$image,
+                $clone,
+                src;
+
+            if (this.active) {
+                return;
+            }
+
+            if (this.$clone) {
+                this.$clone.remove(); // Remove the old clone
+            }
+
+            src = $image.attr("src"); // Don't use "prop"
+            $clone = $('<img src="' + src + '">');
+
+            $clone.on("load", function() {
+                var image;
+
+                $clone.off("load");
+
+                if (this.naturalWidth && this.naturalHeight) {
+                    image = {
+                        naturalHeight: this.naturalHeight,
+                        naturalWidth: this.naturalWidth
+                    };
+                } else {
+                    Cropper.fn.size($clone, {
+                        height: "auto",
+                        width: "auto"
+                    });
+
+                    image = Cropper.fn.size($clone);
+                    image = {
+                        naturalHeight: image.height,
+                        naturalWidth: image.width
+                    };
+                }
+
+                Cropper.fn.size($clone, {
+                    height: "100%",
+                    width: "100%"
+                });
+
+                image.aspectRatio = image.naturalWidth / image.naturalHeight;
+                that.src = src;
+                that.image = image;
+                that.active = true;
+                that.createCropper();
+            });
+
+            if ($.isFunction(callback)) {
+                $image.on("ready.cropper", callback);
+            }
+
+            this.$clone = $clone;
+            $image.after($clone);
+        },
+
+        unrender: function() {
+            if (this.active) {
+                this.active = false;
+                this.removeCropper();
+                this.src = "";
+                this.image = null;
+                this.cropper = null;
+                this.dragger = null;
+            }
+        },
+
+        rerender: function() {
+            this.unrender();
+            this.render();
+        },
+
+        resize: function() {
+            clearTimeout(this.resizing);
+            this.resizing = setTimeout($.proxy(this.rerender, this), 200);
+        },
+
+        createCropper: function() {
+            this.$cropper = $(Cropper.template);
+            this.$dragger = this.$cropper.find(".cropper-dragger");
+            Cropper.fn.toggle(this.$image);
+            this.$image.after(this.$cropper);
+            this.$cropper.prepend(this.$clone);
+
+            if (!this.defaults.modal) {
+                Cropper.fn.toggle(this.$cropper.find(".cropper-modal"));
+            }
+
+            this.setPreview();
+            this.addListener();
+        },
+
+        removeCropper: function() {
+            this.removeListener();
+            this.$preview = null;
+            this.$clone.remove();
+            this.$clone = null;
+            this.$dragger = null;
+            this.$cropper.remove();
+            this.$cropper = null;
+            Cropper.fn.toggle(this.$image);
+        },
+
+        addListener: function() {
+            this.$cropper.bind("mousedown touchstart", $.proxy(this.dragstart, this));
+            this.$cropper.bind("mousemove touchmove", $.proxy(this.dragmove, this));
+            this.$cropper.bind("mouseup mouseleave touchend touchleave", $.proxy(this.dragend, this));
+            $window.on("resize", $.proxy(this.resize, this));
+        },
+
+        removeListener: function() {
+            this.$cropper.unbind("mousedown touchstart", this.dragstart);
+            this.$cropper.unbind("mousemove touchmove", this.dragmove);
+            this.$cropper.unbind("mouseup mouseleave touchend touchleave", this.dragend);
+            $window.off("resize", this.resize);
+        },
+
+        setPreview: function() {
+            var preview = this.defaults.preview;
+
+            this.$preview = this.$cropper.find(".cropper-preview");
+
+            if (typeof preview === "string" && preview.length > 0) {
+                this.$preview = this.$preview.add(preview);
+            }
+
+            this.$preview.html('<img src="' + this.src + '">');
+            this.setCropper();
+        },
+
+        setCropper: function() {
+            var $container = this.$image.parent(),
+                container = Cropper.fn.size($container),
+                image = this.image,
+                cropper;
+
+            if (((image.naturalWidth * container.height / image.naturalHeight) - container.width) >= 0) {
+                cropper = {
+                    height: container.width / image.aspectRatio,
+                    width: container.width,
+                    left: 0
+                };
+
+                cropper.top = (container.height - cropper.height) / 2;
+            } else {
+                cropper = {
+                    height: container.height,
+                    width: container.height * image.aspectRatio,
+                    top: 0
+                };
+
+                cropper.left = (container.width - cropper.width) / 2;
+            }
+
+            $.each(cropper, function(i, n) {
+                cropper[i] = Math.round(n);
+            });
+
+            image.height = cropper.height;
+            image.width = cropper.width;
+            image.ratio = image.width / image.naturalWidth;
+
+            Cropper.fn.position($container);
+            this.$cropper.css({
+                height: cropper.height,
+                left: cropper.left,
+                top: cropper.top,
+                width: cropper.width
+            });
+
+            this.cropper = cropper;
+            this.setDragger();
+        },
+
+        setDragger: function() {
+            var cropper = this.cropper,
+                // If not set, use the original aspect ratio of the image.
+                aspectRatio = this.defaults.aspectRatio || this.image.aspectRatio,
+                dragger;
+
+            if (((cropper.height * aspectRatio) - cropper.width) >= 0) {
+                dragger = {
+                    height: cropper.width / aspectRatio,
+                    width: cropper.width,
+                    left: 0,
+                    top: (cropper.height - (cropper.width / aspectRatio)) / 2,
+                    maxWidth: cropper.width,
+                    maxHeight: cropper.width / aspectRatio
+                };
+            } else {
+                dragger = {
+                    height: cropper.height,
+                    width: cropper.height * aspectRatio,
+                    left: (cropper.width - (cropper.height * aspectRatio)) / 2,
+                    top: 0,
+                    maxHeight: cropper.height,
+                    maxWidth: cropper.height * aspectRatio
+                };
+            }
+
+            dragger.height *= 0.8;
+            dragger.width *= 0.8;
+
+            dragger.left = (cropper.width - dragger.width) / 2;
+            dragger.top = (cropper.height - dragger.height) / 2;
+
+            this.dragger = Cropper.fn.round(dragger);
+            this.setData(this.defaults.data);
+            this.$image.trigger("ready.cropper").off("ready.cropper");
+        },
+
+        resetDragger: function() {
+            var dragger = this.dragger,
+                cropper = this.cropper;
+
+            dragger.width = dragger.width > dragger.maxWidth ? dragger.maxWidth : Math.abs(dragger.width);
+            dragger.height = dragger.height > dragger.maxHeight ? dragger.maxHeight : Math.abs(dragger.height);
+
+            dragger.maxLeft = cropper.width - dragger.width;
+            dragger.maxTop = cropper.height - dragger.height;
+
+            dragger.left = dragger.left < 0 ? 0 : dragger.left > dragger.maxLeft ? dragger.maxLeft : dragger.left;
+            dragger.top = dragger.top < 0 ? 0 : dragger.top > dragger.maxTop ? dragger.maxTop : dragger.top;
+
+            dragger = Cropper.fn.round(dragger);
+
+            this.$dragger.css({
+                height: dragger.height,
+                left: dragger.left,
+                top: dragger.top,
+                width: dragger.width
+            });
+
+            this.dragger = dragger;
+            this.preview();
+            this.output();
+        },
+
+        dragging: function() {
+            var direction = this.direction,
+                dragger = this.dragger,
+                aspectRatio = this.defaults.aspectRatio,
+                range = {
+                    x: this.endX - this.startX,
+                    y: this.endY - this.startY
+                };
+
+            if (aspectRatio) {
+                range.X = range.y * aspectRatio;
+                range.Y = range.x / aspectRatio;
+            }
+
+            switch (direction) {
+
+                // dragging
+                case "e":
+                    dragger.width += range.x;
+
+                    if (aspectRatio) {
+                        dragger.height = dragger.width / aspectRatio;
+                        dragger.top -= range.Y / 2;
+                    }
+
+                    if (dragger.width < 0) {
+                        this.direction = "w";
+                        dragger.width = 0;
+                    }
+
+                    break;
+
+                case "n":
+                    dragger.height -= range.y;
+                    dragger.top += range.y;
+
+                    if (aspectRatio) {
+                        dragger.width = dragger.height * aspectRatio;
+                        dragger.left += range.X / 2;
+                    }
+
+                    if (dragger.height < 0) {
+                        this.direction = "s";
+                        dragger.height = 0;
+                    }
+
+                    break;
+
+                case "w":
+                    dragger.width -= range.x;
+                    dragger.left += range.x;
+
+                    if (aspectRatio) {
+                        dragger.height = dragger.width / aspectRatio;
+                        dragger.top += range.Y / 2;
+                    }
+
+                    if (dragger.width < 0) {
+                        this.direction = "e";
+                        dragger.width = 0;
+                    }
+
+                    break;
+
+                case "s":
+                    dragger.height += range.y;
+
+                    if (aspectRatio) {
+                        dragger.width = dragger.height * aspectRatio;
+                        dragger.left -= range.X / 2;
+                    }
+
+                    if (dragger.height < 0) {
+                        this.direction = "n";
+                        dragger.height = 0;
+                    }
+
+                    break;
+
+                case "ne":
+                    dragger.height -= range.y;
+                    dragger.top += range.y;
+
+                    if (aspectRatio) {
+                        dragger.width = dragger.height * aspectRatio;
+                    } else {
+                        dragger.width += range.x;
+                    }
+
+                    if (dragger.height < 0) {
+                        this.direction = "sw";
+                        dragger.height = 0;
+                        dragger.width = 0;
+                    }
+
+                    break;
+
+                case "nw":
+                    dragger.height -= range.y;
+                    dragger.top += range.y;
+
+                    if (aspectRatio) {
+                        dragger.width = dragger.height * aspectRatio;
+                        dragger.left += range.X;
+                    } else {
+                        dragger.width -= range.x;
+                        dragger.left += range.x;
+                    }
+
+                    if (dragger.height < 0) {
+                        this.direction = "se";
+                        dragger.height = 0;
+                        dragger.width = 0;
+                    }
+
+                    break;
+
+                case "sw":
+                    dragger.width -= range.x;
+                    dragger.left += range.x;
+
+                    if (aspectRatio) {
+                        dragger.height = dragger.width / aspectRatio;
+                    } else {
+                        dragger.height += range.y;
+                    }
+
+                    if (dragger.width < 0) {
+                        this.direction = "ne";
+                        dragger.height = 0;
+                        dragger.width = 0;
+                    }
+
+                    break;
+
+                case "se":
+                    dragger.width += range.x;
+
+                    if (aspectRatio) {
+                        dragger.height = dragger.width / aspectRatio;
+                    } else {
+                        dragger.height += range.y;
+                    }
+
+                    if (dragger.width < 0) {
+                        this.direction = "nw";
+                        dragger.height = 0;
+                        dragger.width = 0;
+                    }
+
+                    break;
+
+                // moving
+                default:
+                    dragger.left += range.x;
+                    dragger.top += range.y;
+            }
+
+            this.resetDragger();
+            this.startX = this.endX;
+            this.startY = this.endY;
+        },
+
+        output: function() {
+            this.defaults.done(this.getData());
+        },
+
+        preview: function() {
+            var that = this,
+                cropper = that.cropper,
+                dragger = that.dragger;
+
+            this.$preview.each(function() {
+                var $this = $(this),
+                    ratio = $this.outerWidth() / dragger.width,
+                    styles = {
+                        height: cropper.height,
+                        marginLeft: - dragger.left,
+                        marginTop: - dragger.top,
+                        width: cropper.width
+                    };
+
+                $this.css({overflow: "hidden"});
+                $this.find("img").css(Cropper.fn.round(styles, function(n) {
+                    return n * ratio;
+                }));
+            });
+        },
+
+        // Public methods
+
+        enable: function(callback) {
+            this.render(callback);
+        },
+
+        disable: function() {
+            this.unrender();
+        },
+
+        setAspectRatio: function(aspectRatio) {
+            if (aspectRatio === "auto" || ($.isNumeric(aspectRatio) && aspectRatio > 0)) {
+                this.defaults.aspectRatio = aspectRatio === "auto" ? NaN : aspectRatio;
+
+                if (this.active) {
+                    this.setDragger();
+                }
+            }
+        },
+
+        setData: function(data) {
+            var cropper = this.cropper,
+                dragger = this.dragger,
+                aspectRatio = this.defaults.aspectRatio,
+                isNumber = function(n) {
+                    return typeof n === "number";
+                };
+
+            if (!this.active) {
+                return;
+            }
+
+            if ($.isPlainObject(data) && !$.isEmptyObject(data)) {
+                data = Cropper.fn.transformData(data, this.image.ratio);
+
+                if (isNumber(data.x1) && data.x1 <= cropper.width) {
+                    dragger.left = data.x1;
+                }
+
+                if (isNumber(data.y1) && data.y1 <= cropper.height) {
+                    dragger.top = data.y1;
+                }
+
+                if (aspectRatio){
+                    if (isNumber(data.width) && data.width <= cropper.width) {
+                        dragger.width = data.width;
+                        dragger.height = dragger.width / aspectRatio;
+                    } else if (isNumber(data.height) && data.height <= cropper.height) {
+                        dragger.height = data.height;
+                        dragger.width = dragger.height * aspectRatio;
+                    } else if (isNumber(data.x2) && data.x2 <= cropper.width) {
+                        dragger.width = data.x2 - dragger.left;
+                        dragger.height = dragger.width / aspectRatio;
+                    } else if (isNumber(data.y2) && data.y2 <= cropper.height) {
+                        dragger.height = data.y2 - dragger.top;
+                        dragger.width = dragger.height * aspectRatio;
+                    }
+                } else {
+                    if (isNumber(data.width) && data.width <= cropper.width) {
+                        dragger.width = data.width;
+                    } else if (isNumber(data.x2) && data.x2 <= cropper.width) {
+                        dragger.width = data.x2 - dragger.left;
+                    }
+
+                    if (isNumber(data.height) && data.height <= cropper.height) {
+                        dragger.height = data.height;
+                    } else if (isNumber(data.y2) && data.height <= cropper.height) {
+                        dragger.height = data.y2 - dragger.top;
+                    }
+                }
+            }
+
+            this.dragger = dragger;
+            this.resetDragger();
+        },
+
+        getData: function() {
+            var dragger = this.dragger,
+                data = {};
+
+            if (this.active) {
+                data = {
+                    x1: dragger.left,
+                    y1: dragger.top,
+                    width: dragger.width,
+                    height: dragger.height,
+                    x2: dragger.left + dragger.width,
+                    y2: dragger.top + dragger.height
+                };
+
+                data = Cropper.fn.transformData(data, (1 / this.image.ratio));
+            }
+
+            return data;
+        },
+
+        setImgSrc: function(src) {
+            if (typeof src === "string" && src.length > 0 && src !== this.src) {
+                this.$image.attr("src", src);
+                this.rerender();
+            }
+        },
+
+        getImgInfo: function() {
+            return this.image || {};
+        },
+
+        // Public events
+
+        dragstart: function(event) {
+            var touches = Cropper.fn.getOriginalEvent(event).touches,
+                e = event,
+                touching,
+                direction;
+
+            if (touches && touches.length === 1) {
+                e = touches[0];
+                this.touchId = e.identifier;
+                touching = true;
+            }
+
+            direction = $(e.target).data().direction;
+
+            if (Cropper.fn.isDirection(direction)) {
+                this.startX = e.pageX;
+                this.startY = e.pageY;
+                this.direction = direction;
+                this.$image.trigger("dragstart");
+                touching && event.preventDefault();
+            }
+        },
+
+        dragmove: function(event) {
+            var touches = Cropper.fn.getOriginalEvent(event).changedTouches,
+                e = event,
+                touching;
+
+            if (touches && touches.length === 1) {
+                e = touches[0];
+                touching = true;
+
+                if (e.identifier !== this.touchId) {
+                    return;
+                }
+            }
+
+            if (this.direction) {
+                this.$image.trigger("dragmove");
+                touching && event.preventDefault();
+                this.endX = e.pageX;
+                this.endY = e.pageY;
+                this.dragging();
+            }
+        },
+
+        dragend: function(event) {
+            var touches = Cropper.fn.getOriginalEvent(event).changedTouches,
+                e = event,
+                touching;
+
+            if (touches && touches.length === 1) {
+                e = touches[0];
+                touching = true;
+
+                if (e.identifier !== this.touchId) {
+                    return;
+                }
+            }
+
+            if (this.direction) {
+                this.direction = "";
+                this.$image.trigger("dragend");
+                touching && event.preventDefault();
+            }
+        }
+    };
+
+    // Common methods
+    Cropper.fn = {
+        toggle: function($e) {
+            $e.toggleClass("cropper-hidden");
+        },
+
+        position: function($e, option) {
+            var position = $e.css("position");
+
+            if (position === "static") {
+                $e.css("position", option || "relative");
+            }
+        },
+
+        size: function($e, options) {
+            if ($.isPlainObject(options)) {
+                $e.css(options);
+            } else {
+                return {
+                    height: $e.height(),
+                    width: $e.width()
+                };
+            }
+        },
+
+        round: function(data, fn) {
+            var value,
+                i;
+
+            for (i in data) {
+                value = data[i];
+
+                if (data.hasOwnProperty(i) && typeof value === "number") {
+                    data[i] = Math.round($.isFunction(fn) ? fn(value) : value);
+                }
+            }
+
+            return data;
+        },
+
+        transformData: function(data, ratio) {
+            var that = this,
+                result = {};
+
+            $.each(data, function(i, n) {
+                if (that.isDataOption(i) && $.isNumeric(n) && n >= 0) {
+                    result[i] = Math.round(n * ratio);
+                }
+            });
+
+            return result;
+        },
+
+        getOriginalEvent: function(event) {
+            if (event && typeof event.originalEvent !== "undefined") {
+               event = event.originalEvent;
+            }
+
+            return event;
+        },
+
+        isDataOption: function(s) {
+            return /^(x1|y1|x2|y2|width|height)$/i.test(s);
+        },
+
+        isDirection: function(s) {
+            return /^(\*|e|n|w|s|ne|nw|sw|se)$/i.test(s);
+        }
+    };
+
+    Cropper.template = [
+        '<div class="cropper-container">',
+            '<div class="cropper-modal"></div>',
+            '<div class="cropper-dragger">',
+                '<span class="cropper-preview"></span>',
+                '<span class="cropper-dashed dashed-h"></span>',
+                '<span class="cropper-dashed dashed-v"></span>',
+                '<span class="cropper-face" data-direction="*"></span>',
+                '<span class="cropper-line line-e" data-direction="e"></span>',
+                '<span class="cropper-line line-n" data-direction="n"></span>',
+                '<span class="cropper-line line-w" data-direction="w"></span>',
+                '<span class="cropper-line line-s" data-direction="s"></span>',
+                '<span class="cropper-point point-e" data-direction="e"></span>',
+                '<span class="cropper-point point-n" data-direction="n"></span>',
+                '<span class="cropper-point point-w" data-direction="w"></span>',
+                '<span class="cropper-point point-s" data-direction="s"></span>',
+                '<span class="cropper-point point-ne" data-direction="ne"></span>',
+                '<span class="cropper-point point-nw" data-direction="nw"></span>',
+                '<span class="cropper-point point-sw" data-direction="sw"></span>',
+                '<span class="cropper-point point-se" data-direction="se"></span>',
+            '</div>',
+        '</div>'
+    ].join("");
+
+    Cropper.defaults = {
+        aspectRatio: "auto",
+        data: {},
+        done: function(/* data */) {},
+        modal: true,
+        preview: ""
+    };
+
+    Cropper.setDefaults = function(options) {
+        $.extend(Cropper.defaults, options);
+    };
+
+    // Register as jQuery plugin
+    $.fn.cropper = function(options, settings) {
+        var result = this;
+
+        this.each(function() {
+            var $this = $(this),
+                data = $this.data("cropper");
+
+            if (!data) {
+                data = new Cropper(this, options);
+                $this.data("cropper", data);
+            }
+
+            if (typeof options === "string" && $.isFunction(data[options])) {
+                result = data[options](settings);
+            }
+        });
+
+        return (typeof result !== "undefined" ? result : this);
+    };
+
+    $.fn.cropper.Constructor = Cropper;
+    $.fn.cropper.setDefaults = Cropper.setDefaults;
+
+    $(function() {
+        $("img[cropper]").cropper();
+    });
+}));

+ 26 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/cropper/index.html

@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebUploader演示 - 带裁剪功能</title>
+<link rel="stylesheet" type="text/css" href="../webuploader.css" />
+</head>
+<body>
+<div id="wrapper">
+	<div class="uploader-container">
+		<div id="filePicker">选择文件</div>
+	</div>
+	
+	<!-- Croper container -->
+	<div class="cropper-wraper webuploader-element-invisible">
+		<div class="img-container"> <img src="" alt="" /> </div>
+		<div class="upload-btn">上传所选区域</div>
+		<div class="img-preview"></div>
+	</div>
+</div>
+<script type="text/javascript" src="../../../jquery/1.9.1/jquery.min.js"></script> 
+<script type="text/javascript" src="../webuploader.min.js"></script> 
+<script type="text/javascript" src="cropper.js"></script> 
+<script type="text/javascript" src="uploader.js"></script>
+</body>
+</html>

+ 268 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/cropper/uploader.js

@@ -0,0 +1,268 @@
+(function( factory ) {
+    if ( !window.jQuery ) {
+        alert('jQuery is required.')
+    }
+
+    jQuery(function() {
+        factory.call( null, jQuery );
+    });
+})(function( $ ) {
+
+var Uploader = (function() {
+
+    // -------setting-------
+    // 如果使用原始大小,超大的图片可能会出现 Croper UI 卡顿,所以这里建议先缩小后再crop.
+    var FRAME_WIDTH = 1600;
+
+
+    var _ = WebUploader;
+    var Uploader = _.Uploader;
+    var uploaderContainer = $('.uploader-container');
+    var uploader, file;
+
+    if ( !Uploader.support() ) {
+        alert( 'Web Uploader 不支持您的浏览器!');
+        throw new Error( 'WebUploader does not support the browser you are using.' );
+    }
+
+    // hook,
+    // 在文件开始上传前进行裁剪。
+    Uploader.register({
+        'before-send-file': 'cropImage'
+    }, {
+
+        cropImage: function( file ) {
+
+            var data = file._cropData,
+                image, deferred;
+
+            file = this.request( 'get-file', file );
+            deferred = _.Deferred();
+
+            image = new _.Lib.Image();
+
+            deferred.always(function() {
+                image.destroy();
+                image = null;
+            });
+            image.once( 'error', deferred.reject );
+            image.once( 'load', function() {
+                image.crop( data.x, data.y, data.width, data.height, data.scale );
+            });
+
+            image.once( 'complete', function() {
+                var blob, size;
+
+                // 移动端 UC / qq 浏览器的无图模式下
+                // ctx.getImageData 处理大图的时候会报 Exception
+                // INDEX_SIZE_ERR: DOM Exception 1
+                try {
+                    blob = image.getAsBlob();
+                    size = file.size;
+                    file.source = blob;
+                    file.size = blob.size;
+
+                    file.trigger( 'resize', blob.size, size );
+
+                    deferred.resolve();
+                } catch ( e ) {
+                    console.log( e );
+                    // 出错了直接继续,让其上传原始图片
+                    deferred.resolve();
+                }
+            });
+
+            file._info && image.info( file._info );
+            file._meta && image.meta( file._meta );
+            image.loadFromBlob( file.source );
+            return deferred.promise();
+        }
+    });
+
+    return {
+        init: function( selectCb ) {
+            uploader = new Uploader({
+                pick: {
+                    id: '#filePicker',
+                    multiple: false
+                },
+
+                // 设置用什么方式去生成缩略图。
+                thumb: {
+                    quality: 70,
+
+                    // 不允许放大
+                    allowMagnify: false,
+
+                    // 是否采用裁剪模式。如果采用这样可以避免空白内容。
+                    crop: false
+                },
+
+                // 禁掉分块传输,默认是开起的。
+                chunked: false,
+
+                // 禁掉上传前压缩功能,因为会手动裁剪。
+                compress: false,
+
+                // fileSingleSizeLimit: 2 * 1024 * 1024,
+
+                server: '../server/fileupload.php',
+                swf: '../Uploader.swf',
+                fileNumLimit: 1,
+                onError: function() {
+                    var args = [].slice.call(arguments, 0);
+                    alert(args.join('\n'));
+                }
+            });
+
+            uploader.on('fileQueued', function( _file ) {
+                file = _file;
+
+                uploader.makeThumb( file, function( error, src ) {
+
+                    if ( error ) {
+                        alert('不能预览');
+                        return;
+                    }
+
+                    selectCb( src );
+
+                }, FRAME_WIDTH, 1 );   // 注意这里的 height 值是 1,被当成了 100% 使用。
+            });
+        },
+
+        crop: function( data ) {
+
+            var scale = Croper.getImageSize().width / file._info.width;
+            data.scale = scale;
+
+            file._cropData = {
+                x: data.x1,
+                y: data.y1,
+                width: data.width,
+                height: data.height,
+                scale: data.scale
+            };
+        },
+
+        upload: function() {
+            uploader.upload();
+        }
+    }
+})();
+
+
+var Croper = (function() {
+    var container = $('.cropper-wraper');
+    var $image = container.find('.img-container img');
+    var btn = $('.upload-btn');
+    var isBase64Supported, callback;
+
+    $image.cropper({
+        aspectRatio: 16 / 9,
+        preview: ".img-preview",
+        done: function(data) {
+            // console.log(data);
+        }
+    });
+
+    function srcWrap( src, cb ) {
+
+        // we need to check this at the first time.
+        if (typeof isBase64Supported === 'undefined') {
+            (function() {
+                var data = new Image();
+                var support = true;
+                data.onload = data.onerror = function() {
+                    if( this.width != 1 || this.height != 1 ) {
+                        support = false;
+                    }
+                }
+                data.src = src;
+                isBase64Supported = support;
+            })();
+        }
+
+        if ( isBase64Supported ) {
+            cb( src );
+        } else {
+            // otherwise we need server support.
+            // convert base64 to a file.
+            $.ajax('../server/preview.php', {
+                method: 'POST',
+                data: src,
+                dataType:'json'
+            }).done(function( response ) {
+                if (response.result) {
+                    cb( response.result );
+                } else {
+                    alert("预览出错");
+                }
+            });
+        }
+    }
+
+    btn.on('click', function() {
+        callback && callback($image.cropper("getData"));
+        return false;
+    });
+
+    return {
+        setSource: function( src ) {
+
+            // 处理 base64 不支持的情况。
+            // 一般出现在 ie6-ie8
+            srcWrap( src, function( src ) {
+                $image.cropper("setImgSrc", src);
+            });
+
+            container.removeClass('webuploader-element-invisible');
+
+            return this;
+        },
+
+        getImageSize: function() {
+            var img = $image.get(0);
+            return {
+                width: img.naturalWidth,
+                height: img.naturalHeight
+            }
+        },
+
+        setCallback: function( cb ) {
+            callback = cb;
+            return this;
+        },
+
+        disable: function() {
+            $image.cropper("disable");
+            return this;
+        },
+
+        enable: function() {
+            $image.cropper("enable");
+            return this;
+        }
+    }
+
+})();
+
+
+
+var container = $('.uploader-container');
+
+Uploader.init(function( src ) {
+
+    Croper.setSource( src );
+
+    // 隐藏选择按钮。
+    container.addClass('webuploader-element-invisible');
+
+    // 当用户选择上传的时候,开始上传。
+    Croper.setCallback(function( data ) {
+        Uploader.crop(data);
+        Uploader.upload();
+    });
+});
+
+});

BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/expressInstall.swf


+ 29 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/image-upload/index.html

@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebUploader演示</title>
+<link rel="stylesheet" type="text/css" href="../webuploader.css" />
+</head>
+<body>
+<div class="uploader-list-container">
+	<div class="queueList">
+		<div id="dndArea" class="placeholder">
+			<div id="filePicker-2"></div>
+			<p>或将照片拖到这里,单次最多可选300张</p>
+		</div>
+	</div>
+	<div class="statusBar" style="display:none;">
+		<div class="progress"> <span class="text">0%</span> <span class="percentage"></span> </div>
+		<div class="info"></div>
+		<div class="btns">
+			<div id="filePicker2"></div>
+			<div class="uploadBtn">开始上传</div>
+		</div>
+	</div>
+</div>
+<script type="text/javascript" src="../../../jquery/1.9.1/jquery.min.js"></script> 
+<script type="text/javascript" src="../webuploader.min.js"></script> 
+<script type="text/javascript" src="upload.js"></script>
+</body>
+</html>

+ 573 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/image-upload/upload.js

@@ -0,0 +1,573 @@
+(function( $ ){
+    // 当domReady的时候开始初始化
+    $(function() {
+        var $wrap = $('.uploader-list-container'),
+
+            // 图片容器
+            $queue = $( '<ul class="filelist"></ul>' )
+                .appendTo( $wrap.find( '.queueList' ) ),
+
+            // 状态栏,包括进度和控制按钮
+            $statusBar = $wrap.find( '.statusBar' ),
+
+            // 文件总体选择信息。
+            $info = $statusBar.find( '.info' ),
+
+            // 上传按钮
+            $upload = $wrap.find( '.uploadBtn' ),
+
+            // 没选择文件之前的内容。
+            $placeHolder = $wrap.find( '.placeholder' ),
+
+            $progress = $statusBar.find( '.progress' ).hide(),
+
+            // 添加的文件数量
+            fileCount = 0,
+
+            // 添加的文件总大小
+            fileSize = 0,
+
+            // 优化retina, 在retina下这个值是2
+            ratio = window.devicePixelRatio || 1,
+
+            // 缩略图大小
+            thumbnailWidth = 110 * ratio,
+            thumbnailHeight = 110 * ratio,
+
+            // 可能有pedding, ready, uploading, confirm, done.
+            state = 'pedding',
+
+            // 所有文件的进度信息,key为file id
+            percentages = {},
+            // 判断浏览器是否支持图片的base64
+            isSupportBase64 = ( function() {
+                var data = new Image();
+                var support = true;
+                data.onload = data.onerror = function() {
+                    if( this.width != 1 || this.height != 1 ) {
+                        support = false;
+                    }
+                }
+                data.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
+                return support;
+            } )(),
+
+            // 检测是否已经安装flash,检测flash的版本
+            flashVersion = ( function() {
+                var version;
+
+                try {
+                    version = navigator.plugins[ 'Shockwave Flash' ];
+                    version = version.description;
+                } catch ( ex ) {
+                    try {
+                        version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')
+                                .GetVariable('$version');
+                    } catch ( ex2 ) {
+                        version = '0.0';
+                    }
+                }
+                version = version.match( /\d+/g );
+                return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );
+            } )(),
+
+            supportTransition = (function(){
+                var s = document.createElement('p').style,
+                    r = 'transition' in s ||
+                            'WebkitTransition' in s ||
+                            'MozTransition' in s ||
+                            'msTransition' in s ||
+                            'OTransition' in s;
+                s = null;
+                return r;
+            })(),
+
+            // WebUploader实例
+            uploader;
+
+        if ( !WebUploader.Uploader.support('flash') && WebUploader.browser.ie ) {
+
+            // flash 安装了但是版本过低。
+            if (flashVersion) {
+                (function(container) {
+                    window['expressinstallcallback'] = function( state ) {
+                        switch(state) {
+                            case 'Download.Cancelled':
+                                alert('您取消了更新!')
+                                break;
+
+                            case 'Download.Failed':
+                                alert('安装失败')
+                                break;
+
+                            default:
+                                alert('安装已成功,请刷新!');
+                                break;
+                        }
+                        delete window['expressinstallcallback'];
+                    };
+
+                    var swf = 'expressInstall.swf';
+                    // insert flash object
+                    var html = '<object type="application/' +
+                            'x-shockwave-flash" data="' +  swf + '" ';
+
+                    if (WebUploader.browser.ie) {
+                        html += 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ';
+                    }
+
+                    html += 'width="100%" height="100%" style="outline:0">'  +
+                        '<param name="movie" value="' + swf + '" />' +
+                        '<param name="wmode" value="transparent" />' +
+                        '<param name="allowscriptaccess" value="always" />' +
+                    '</object>';
+
+                    container.html(html);
+
+                })($wrap);
+
+            // 压根就没有安转。
+            } else {
+                $wrap.html('<a href="http://www.adobe.com/go/getflashplayer" target="_blank" border="0"><img alt="get flash player" src="http://www.adobe.com/macromedia/style_guide/images/160x41_Get_Flash_Player.jpg" /></a>');
+            }
+
+            return;
+        } else if (!WebUploader.Uploader.support()) {
+            alert( 'Web Uploader 不支持您的浏览器!');
+            return;
+        }
+
+        // 实例化
+        uploader = WebUploader.create({
+            pick: {
+                id: '#filePicker-2',
+                label: '点击选择图片'
+            },
+            formData: {
+                uid: 123
+            },
+            dnd: '#dndArea',
+            paste: '#uploader',
+            swf: '../Uploader.swf',
+            chunked: false,
+            chunkSize: 512 * 1024,
+            server: '../server/fileupload.php',
+            // runtimeOrder: 'flash',
+
+            // accept: {
+            //     title: 'Images',
+            //     extensions: 'gif,jpg,jpeg,bmp,png',
+            //     mimeTypes: 'image/*'
+            // },
+
+            // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候,把图片打开。
+            disableGlobalDnd: true,
+            fileNumLimit: 300,
+            fileSizeLimit: 200 * 1024 * 1024,    // 200 M
+            fileSingleSizeLimit: 50 * 1024 * 1024    // 50 M
+        });
+
+        // 拖拽时不接受 js, txt 文件。
+        uploader.on( 'dndAccept', function( items ) {
+            var denied = false,
+                len = items.length,
+                i = 0,
+                // 修改js类型
+                unAllowed = 'text/plain;application/javascript ';
+
+            for ( ; i < len; i++ ) {
+                // 如果在列表里面
+                if ( ~unAllowed.indexOf( items[ i ].type ) ) {
+                    denied = true;
+                    break;
+                }
+            }
+
+            return !denied;
+        });
+
+        uploader.on('dialogOpen', function() {
+            console.log('here');
+        });
+
+        // uploader.on('filesQueued', function() {
+        //     uploader.sort(function( a, b ) {
+        //         if ( a.name < b.name )
+        //           return -1;
+        //         if ( a.name > b.name )
+        //           return 1;
+        //         return 0;
+        //     });
+        // });
+
+        // 添加“添加文件”的按钮,
+        uploader.addButton({
+            id: '#filePicker2',
+            label: '继续添加'
+        });
+
+        uploader.on('ready', function() {
+            window.uploader = uploader;
+        });
+
+        // 当有文件添加进来时执行,负责view的创建
+        function addFile( file ) {
+            var $li = $( '<li id="' + file.id + '">' +
+                    '<p class="title">' + file.name + '</p>' +
+                    '<p class="imgWrap"></p>'+
+                    '<p class="progress"><span></span></p>' +
+                    '</li>' ),
+
+                $btns = $('<div class="file-panel">' +
+                    '<span class="cancel">删除</span>' +
+                    '<span class="rotateRight">向右旋转</span>' +
+                    '<span class="rotateLeft">向左旋转</span></div>').appendTo( $li ),
+                $prgress = $li.find('p.progress span'),
+                $wrap = $li.find( 'p.imgWrap' ),
+                $info = $('<p class="error"></p>'),
+
+                showError = function( code ) {
+                    switch( code ) {
+                        case 'exceed_size':
+                            text = '文件大小超出';
+                            break;
+
+                        case 'interrupt':
+                            text = '上传暂停';
+                            break;
+
+                        default:
+                            text = '上传失败,请重试';
+                            break;
+                    }
+
+                    $info.text( text ).appendTo( $li );
+                };
+
+            if ( file.getStatus() === 'invalid' ) {
+                showError( file.statusText );
+            } else {
+                // @todo lazyload
+                $wrap.text( '预览中' );
+                uploader.makeThumb( file, function( error, src ) {
+                    var img;
+
+                    if ( error ) {
+                        $wrap.text( '不能预览' );
+                        return;
+                    }
+
+                    if( isSupportBase64 ) {
+                        img = $('<img src="'+src+'">');
+                        $wrap.empty().append( img );
+                    } else {
+                        $.ajax('../server/preview.php', {
+                            method: 'POST',
+                            data: src,
+                            dataType:'json'
+                        }).done(function( response ) {
+                            if (response.result) {
+                                img = $('<img src="'+response.result+'">');
+                                $wrap.empty().append( img );
+                            } else {
+                                $wrap.text("预览出错");
+                            }
+                        });
+                    }
+                }, thumbnailWidth, thumbnailHeight );
+
+                percentages[ file.id ] = [ file.size, 0 ];
+                file.rotation = 0;
+            }
+
+            file.on('statuschange', function( cur, prev ) {
+                if ( prev === 'progress' ) {
+                    $prgress.hide().width(0);
+                } else if ( prev === 'queued' ) {
+                    $li.off( 'mouseenter mouseleave' );
+                    $btns.remove();
+                }
+
+                // 成功
+                if ( cur === 'error' || cur === 'invalid' ) {
+                    console.log( file.statusText );
+                    showError( file.statusText );
+                    percentages[ file.id ][ 1 ] = 1;
+                } else if ( cur === 'interrupt' ) {
+                    showError( 'interrupt' );
+                } else if ( cur === 'queued' ) {
+                    percentages[ file.id ][ 1 ] = 0;
+                } else if ( cur === 'progress' ) {
+                    $info.remove();
+                    $prgress.css('display', 'block');
+                } else if ( cur === 'complete' ) {
+                    $li.append( '<span class="success"></span>' );
+                }
+
+                $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );
+            });
+
+            $li.on( 'mouseenter', function() {
+                $btns.stop().animate({height: 30});
+            });
+
+            $li.on( 'mouseleave', function() {
+                $btns.stop().animate({height: 0});
+            });
+
+            $btns.on( 'click', 'span', function() {
+                var index = $(this).index(),
+                    deg;
+
+                switch ( index ) {
+                    case 0:
+                        uploader.removeFile( file );
+                        return;
+
+                    case 1:
+                        file.rotation += 90;
+                        break;
+
+                    case 2:
+                        file.rotation -= 90;
+                        break;
+                }
+
+                if ( supportTransition ) {
+                    deg = 'rotate(' + file.rotation + 'deg)';
+                    $wrap.css({
+                        '-webkit-transform': deg,
+                        '-mos-transform': deg,
+                        '-o-transform': deg,
+                        'transform': deg
+                    });
+                } else {
+                    $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');
+                    // use jquery animate to rotation
+                    // $({
+                    //     rotation: rotation
+                    // }).animate({
+                    //     rotation: file.rotation
+                    // }, {
+                    //     easing: 'linear',
+                    //     step: function( now ) {
+                    //         now = now * Math.PI / 180;
+
+                    //         var cos = Math.cos( now ),
+                    //             sin = Math.sin( now );
+
+                    //         $wrap.css( 'filter', "progid:DXImageTransform.Microsoft.Matrix(M11=" + cos + ",M12=" + (-sin) + ",M21=" + sin + ",M22=" + cos + ",SizingMethod='auto expand')");
+                    //     }
+                    // });
+                }
+
+
+            });
+
+            $li.appendTo( $queue );
+        }
+
+        // 负责view的销毁
+        function removeFile( file ) {
+            var $li = $('#'+file.id);
+
+            delete percentages[ file.id ];
+            updateTotalProgress();
+            $li.off().find('.file-panel').off().end().remove();
+        }
+
+        function updateTotalProgress() {
+            var loaded = 0,
+                total = 0,
+                spans = $progress.children(),
+                percent;
+
+            $.each( percentages, function( k, v ) {
+                total += v[ 0 ];
+                loaded += v[ 0 ] * v[ 1 ];
+            } );
+
+            percent = total ? loaded / total : 0;
+
+
+            spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' );
+            spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' );
+            updateStatus();
+        }
+
+        function updateStatus() {
+            var text = '', stats;
+
+            if ( state === 'ready' ) {
+                text = '选中' + fileCount + '张图片,共' +
+                        WebUploader.formatSize( fileSize ) + '。';
+            } else if ( state === 'confirm' ) {
+                stats = uploader.getStats();
+                if ( stats.uploadFailNum ) {
+                    text = '已成功上传' + stats.successNum+ '张照片至XX相册,'+
+                        stats.uploadFailNum + '张照片上传失败,<a class="retry" href="#">重新上传</a>失败图片或<a class="ignore" href="#">忽略</a>'
+                }
+
+            } else {
+                stats = uploader.getStats();
+                text = '共' + fileCount + '张(' +
+                        WebUploader.formatSize( fileSize )  +
+                        '),已上传' + stats.successNum + '张';
+
+                if ( stats.uploadFailNum ) {
+                    text += ',失败' + stats.uploadFailNum + '张';
+                }
+            }
+
+            $info.html( text );
+        }
+
+        function setState( val ) {
+            var file, stats;
+
+            if ( val === state ) {
+                return;
+            }
+
+            $upload.removeClass( 'state-' + state );
+            $upload.addClass( 'state-' + val );
+            state = val;
+
+            switch ( state ) {
+                case 'pedding':
+                    $placeHolder.removeClass( 'element-invisible' );
+                    $queue.hide();
+                    $statusBar.addClass( 'element-invisible' );
+                    uploader.refresh();
+                    break;
+
+                case 'ready':
+                    $placeHolder.addClass( 'element-invisible' );
+                    $( '#filePicker2' ).removeClass( 'element-invisible');
+                    $queue.show();
+                    $statusBar.removeClass('element-invisible');
+                    uploader.refresh();
+                    break;
+
+                case 'uploading':
+                    $( '#filePicker2' ).addClass( 'element-invisible' );
+                    $progress.show();
+                    $upload.text( '暂停上传' );
+                    break;
+
+                case 'paused':
+                    $progress.show();
+                    $upload.text( '继续上传' );
+                    break;
+
+                case 'confirm':
+                    $progress.hide();
+                    $( '#filePicker2' ).removeClass( 'element-invisible' );
+                    $upload.text( '开始上传' );
+
+                    stats = uploader.getStats();
+                    if ( stats.successNum && !stats.uploadFailNum ) {
+                        setState( 'finish' );
+                        return;
+                    }
+                    break;
+                case 'finish':
+                    stats = uploader.getStats();
+                    if ( stats.successNum ) {
+                        alert( '上传成功' );
+                    } else {
+                        // 没有成功的图片,重设
+                        state = 'done';
+                        location.reload();
+                    }
+                    break;
+            }
+
+            updateStatus();
+        }
+
+        uploader.onUploadProgress = function( file, percentage ) {
+            var $li = $('#'+file.id),
+                $percent = $li.find('.progress span');
+
+            $percent.css( 'width', percentage * 100 + '%' );
+            percentages[ file.id ][ 1 ] = percentage;
+            updateTotalProgress();
+        };
+
+        uploader.onFileQueued = function( file ) {
+            fileCount++;
+            fileSize += file.size;
+
+            if ( fileCount === 1 ) {
+                $placeHolder.addClass( 'element-invisible' );
+                $statusBar.show();
+            }
+
+            addFile( file );
+            setState( 'ready' );
+            updateTotalProgress();
+        };
+
+        uploader.onFileDequeued = function( file ) {
+            fileCount--;
+            fileSize -= file.size;
+
+            if ( !fileCount ) {
+                setState( 'pedding' );
+            }
+
+            removeFile( file );
+            updateTotalProgress();
+
+        };
+
+        uploader.on( 'all', function( type ) {
+            var stats;
+            switch( type ) {
+                case 'uploadFinished':
+                    setState( 'confirm' );
+                    break;
+
+                case 'startUpload':
+                    setState( 'uploading' );
+                    break;
+
+                case 'stopUpload':
+                    setState( 'paused' );
+                    break;
+
+            }
+        });
+
+        uploader.onError = function( code ) {
+            alert( 'Eroor: ' + code );
+        };
+
+        $upload.on('click', function() {
+            if ( $(this).hasClass( 'disabled' ) ) {
+                return false;
+            }
+
+            if ( state === 'ready' ) {
+                uploader.upload();
+            } else if ( state === 'paused' ) {
+                uploader.upload();
+            } else if ( state === 'uploading' ) {
+                uploader.stop();
+            }
+        });
+
+        $info.on( 'click', '.retry', function() {
+            uploader.retry();
+        } );
+
+        $info.on( 'click', '.ignore', function() {
+            alert( 'todo' );
+        } );
+
+        $upload.addClass( 'state-' + state );
+        updateTotalProgress();
+    });
+
+})( jQuery );

BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/Thumbs.db


BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/bg.png


BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/icons.png


BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/icons.psd


BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/image.png


BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/progress.png


BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/progress.psd


BIN
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/images/success.png


+ 20 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/md5-demo/index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>WebUploader演示 - 带裁剪功能</title>
+<link rel="stylesheet" type="text/css" href="../webuploader.css" />
+</head>
+<body>
+<div id="wrapper">
+	<div class="uploader-container">
+		<div id="filePicker">html5版本</div>
+		<div id="filePicker2">flash版本</div>
+	</div>
+	<div id="log"> <strong>console 会影响 md5 时间的计算,所以在测试 md5 速度的时候,把 console 关了</strong> </div>
+</div>
+<script type="text/javascript" src="../../../jquery/1.9.1/jquery.min.js"></script> 
+<script type="text/javascript" src="../webuploader.min.js"></script> 
+<script type="text/javascript" src="script.js"></script>
+</body>
+</html>

+ 57 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/md5-demo/script.js

@@ -0,0 +1,57 @@
+(function($) {
+    $(function() {
+        var log = (function() {
+            var dom = $('#log');
+
+            return function( str ) {
+                dom.append('<p>' + str + '</p>')
+            }
+        })();
+
+        WebUploader.create({
+            pick: '#filePicker'
+        }).on('fileQueued', function( file ) {
+            var start =  +new Date();
+
+            // 返回的是 promise 对象
+            this.md5File(file, 0, 1 * 1024 * 1024)
+
+                // 可以用来监听进度
+                .progress(function(percentage) {
+                    // console.log('Percentage:', percentage);
+                })
+
+                // 处理完成后触发
+                .then(function(ret) {
+                    // console.log('md5:', ret);
+                    
+                    var end = +new Date();
+                    log('HTML5: md5 ' + file.name + ' cost ' + (end - start) + 'ms get value: ' + ret);
+                });
+        });
+
+        WebUploader.create({
+            pick: '#filePicker2',
+            swf: '../Uploader.swf',
+            runtimeOrder: 'flash'
+        }).on('fileQueued', function( file ) {
+            var start =  +new Date();
+
+            // 返回的是 promise 对象
+            this.md5File(file, 0, 1 * 1024 * 1024)
+
+                // 可以用来监听进度
+                .progress(function(percentage) {
+                    // console.log('Percentage:', percentage);
+                })
+
+                // 处理完成后触发
+                .then(function(ret) {
+                    // console.log('md5:', ret);
+                    
+                    var end = +new Date();
+                    log('Flash: md5 ' + file.name + ' cost ' + (end - start) + 'ms get value: ' + ret);
+                });
+        });
+    });
+})(jQuery);

+ 430 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/requirejs/app.js

@@ -0,0 +1,430 @@
+requirejs.config({
+    baseUrl: '../../dist',
+    paths: {
+        jquery: '../examples/image-upload/jquery'
+    }
+});
+
+require([ 'webuploader.flashonly' ], function( WebUploader ) {
+    // 当domReady的时候开始初始化
+    $(function() {
+        var $wrap = $('#uploader'),
+
+            // 图片容器
+            $queue = $( '<ul class="filelist"></ul>' )
+                .appendTo( $wrap.find( '.queueList' ) ),
+
+            // 状态栏,包括进度和控制按钮
+            $statusBar = $wrap.find( '.statusBar' ),
+
+            // 文件总体选择信息。
+            $info = $statusBar.find( '.info' ),
+
+            // 上传按钮
+            $upload = $wrap.find( '.uploadBtn' ),
+
+            // 没选择文件之前的内容。
+            $placeHolder = $wrap.find( '.placeholder' ),
+
+            $progress = $statusBar.find( '.progress' ).hide(),
+
+            // 添加的文件数量
+            fileCount = 0,
+
+            // 添加的文件总大小
+            fileSize = 0,
+
+            // 优化retina, 在retina下这个值是2
+            ratio = window.devicePixelRatio || 1,
+
+            // 缩略图大小
+            thumbnailWidth = 110 * ratio,
+            thumbnailHeight = 110 * ratio,
+
+            // 可能有pedding, ready, uploading, confirm, done.
+            state = 'pedding',
+
+            // 所有文件的进度信息,key为file id
+            percentages = {},
+
+            supportTransition = (function(){
+                var s = document.createElement('p').style,
+                    r = 'transition' in s ||
+                          'WebkitTransition' in s ||
+                          'MozTransition' in s ||
+                          'msTransition' in s ||
+                          'OTransition' in s;
+                s = null;
+                return r;
+            })(),
+
+            // WebUploader实例
+            uploader;
+
+        // 实例化
+        uploader = WebUploader.create({
+            pick: {
+                id: '#filePicker',
+                label: '点击选择图片'
+            },
+            dnd: '#dndArea',
+            paste: '#uploader',
+            swf: '../../dist/Uploader.swf',
+            chunked: true,
+            // runtimeOrder: 'flash',
+            sendAsBinary: true,
+            server: '../../server/fileupload.php',
+            // server: 'http://liaoxuezhi.fe.baidu.com/webupload/fileupload.php',
+            // server: 'http://www.2betop.net/fileupload.php',
+            fileNumLimit: 300,
+            fileSizeLimit: 200 * 1024 * 1024,    // 200 M
+            fileSingleSizeLimit: 50 * 1024 * 1024    // 50 M
+        });
+
+        // 添加“添加文件”的按钮,
+        uploader.addButton({
+            id: '#filePicker2',
+            label: '继续添加'
+        });
+
+        // 当有文件添加进来时执行,负责view的创建
+        function addFile( file ) {
+            var $li = $( '<li id="' + file.id + '">' +
+                    '<p class="title">' + file.name + '</p>' +
+                    '<p class="imgWrap"></p>'+
+                    '<p class="progress"><span></span></p>' +
+                    '</li>' ),
+
+                $btns = $('<div class="file-panel">' +
+                    '<span class="cancel">删除</span>' +
+                    '<span class="rotateRight">向右旋转</span>' +
+                    '<span class="rotateLeft">向左旋转</span></div>').appendTo( $li ),
+                $prgress = $li.find('p.progress span'),
+                $wrap = $li.find( 'p.imgWrap' ),
+                $info = $('<p class="error"></p>'),
+
+                showError = function( code ) {
+                    switch( code ) {
+                        case 'exceed_size':
+                            text = '文件大小超出';
+                            break;
+
+                        case 'interrupt':
+                            text = '上传暂停';
+                            break;
+
+                        default:
+                            text = '上传失败,请重试';
+                            break;
+                    }
+
+                    $info.text( text ).appendTo( $li );
+                };
+
+            if ( file.getStatus() === 'invalid' ) {
+                showError( file.statusText );
+            } else {
+                // @todo lazyload
+                $wrap.text( '预览中' );
+                uploader.makeThumb( file, function( error, src ) {
+                    if ( error ) {
+                        $wrap.text( '不能预览' );
+                        return;
+                    }
+
+                    var img = $('<img src="'+src+'">');
+                    $wrap.empty().append( img );
+                }, thumbnailWidth, thumbnailHeight );
+
+                percentages[ file.id ] = [ file.size, 0 ];
+                file.rotation = 0;
+            }
+
+            file.on('statuschange', function( cur, prev ) {
+                if ( prev === 'progress' ) {
+                    $prgress.hide().width(0);
+                } else if ( prev === 'queued' ) {
+                    $li.off( 'mouseenter mouseleave' );
+                    $btns.remove();
+                }
+
+                // 成功
+                if ( cur === 'error' || cur === 'invalid' ) {
+                    console.log( file.statusText );
+                    showError( file.statusText );
+                    percentages[ file.id ][ 1 ] = 1;
+                } else if ( cur === 'interrupt' ) {
+                    showError( 'interrupt' );
+                } else if ( cur === 'queued' ) {
+                    percentages[ file.id ][ 1 ] = 0;
+                } else if ( cur === 'progress' ) {
+                    $info.remove();
+                    $prgress.css('display', 'block');
+                } else if ( cur === 'complete' ) {
+                    $li.append( '<span class="success"></span>' );
+                }
+
+                $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );
+            });
+
+            $li.on( 'mouseenter', function() {
+                $btns.stop().animate({height: 30});
+            });
+
+            $li.on( 'mouseleave', function() {
+                $btns.stop().animate({height: 0});
+            });
+
+            $btns.on( 'click', 'span', function() {
+                var index = $(this).index(),
+                    deg;
+
+                switch ( index ) {
+                    case 0:
+                        uploader.removeFile( file );
+                        return;
+
+                    case 1:
+                        file.rotation += 90;
+                        break;
+
+                    case 2:
+                        file.rotation -= 90;
+                        break;
+                }
+
+                if ( supportTransition ) {
+                    deg = 'rotate(' + file.rotation + 'deg)';
+                    $wrap.css({
+                        '-webkit-transform': deg,
+                        '-mos-transform': deg,
+                        '-o-transform': deg,
+                        'transform': deg
+                    });
+                } else {
+                    $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');
+                    // use jquery animate to rotation
+                    // $({
+                    //     rotation: rotation
+                    // }).animate({
+                    //     rotation: file.rotation
+                    // }, {
+                    //     easing: 'linear',
+                    //     step: function( now ) {
+                    //         now = now * Math.PI / 180;
+
+                    //         var cos = Math.cos( now ),
+                    //             sin = Math.sin( now );
+
+                    //         $wrap.css( 'filter', "progid:DXImageTransform.Microsoft.Matrix(M11=" + cos + ",M12=" + (-sin) + ",M21=" + sin + ",M22=" + cos + ",SizingMethod='auto expand')");
+                    //     }
+                    // });
+                }
+
+
+            });
+
+            $li.appendTo( $queue );
+        }
+
+        // 负责view的销毁
+        function removeFile( file ) {
+            var $li = $('#'+file.id);
+
+            delete percentages[ file.id ];
+            updateTotalProgress();
+            $li.off().find('.file-panel').off().end().remove();
+        }
+
+        function updateTotalProgress() {
+            var loaded = 0,
+                total = 0,
+                spans = $progress.children(),
+                percent;
+
+            $.each( percentages, function( k, v ) {
+                total += v[ 0 ];
+                loaded += v[ 0 ] * v[ 1 ];
+            } );
+
+            percent = total ? loaded / total : 0;
+
+            spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' );
+            spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' );
+            updateStatus();
+        }
+
+        function updateStatus() {
+            var text = '', stats;
+
+            if ( state === 'ready' ) {
+                text = '选中' + fileCount + '张图片,共' +
+                        WebUploader.formatSize( fileSize ) + '。';
+            } else if ( state === 'confirm' ) {
+                stats = uploader.getStats();
+                if ( stats.uploadFailNum ) {
+                    text = '已成功上传' + stats.successNum+ '张照片至XX相册,'+
+                        stats.uploadFailNum + '张照片上传失败,<a class="retry" href="#">重新上传</a>失败图片或<a class="ignore" href="#">忽略</a>'
+                }
+
+            } else {
+                stats = uploader.getStats();
+                text = '共' + fileCount + '张(' +
+                        WebUploader.formatSize( fileSize )  +
+                        '),已上传' + stats.successNum + '张';
+
+                if ( stats.uploadFailNum ) {
+                    text += ',失败' + stats.uploadFailNum + '张';
+                }
+            }
+
+            $info.html( text );
+        }
+
+        function setState( val ) {
+            var file, stats;
+
+            if ( val === state ) {
+                return;
+            }
+
+            $upload.removeClass( 'state-' + state );
+            $upload.addClass( 'state-' + val );
+            state = val;
+
+            switch ( state ) {
+                case 'pedding':
+                    $placeHolder.removeClass( 'element-invisible' );
+                    $queue.hide();
+                    $statusBar.addClass( 'element-invisible' );
+                    uploader.refresh();
+                    break;
+
+                case 'ready':
+                    $placeHolder.addClass( 'element-invisible' );
+                    $( '#filePicker2' ).removeClass( 'element-invisible');
+                    $queue.show();
+                    $statusBar.removeClass('element-invisible');
+                    uploader.refresh();
+                    break;
+
+                case 'uploading':
+                    $( '#filePicker2' ).addClass( 'element-invisible' );
+                    $progress.show();
+                    $upload.text( '暂停上传' );
+                    break;
+
+                case 'paused':
+                    $progress.show();
+                    $upload.text( '继续上传' );
+                    break;
+
+                case 'confirm':
+                    $progress.hide();
+                    $upload.text( '开始上传' ).addClass( 'disabled' );
+
+                    stats = uploader.getStats();
+                    if ( stats.successNum && !stats.uploadFailNum ) {
+                        setState( 'finish' );
+                        return;
+                    }
+                    break;
+                case 'finish':
+                    stats = uploader.getStats();
+                    if ( stats.successNum ) {
+                        alert( '上传成功' );
+                    } else {
+                        // 没有成功的图片,重设
+                        state = 'done';
+                        location.reload();
+                    }
+                    break;
+            }
+
+            updateStatus();
+        }
+
+        uploader.onUploadProgress = function( file, percentage ) {
+            var $li = $('#'+file.id),
+                $percent = $li.find('.progress span');
+
+            $percent.css( 'width', percentage * 100 + '%' );
+            percentages[ file.id ][ 1 ] = percentage;
+            updateTotalProgress();
+        };
+
+        uploader.onFileQueued = function( file ) {
+            fileCount++;
+            fileSize += file.size;
+
+            if ( fileCount === 1 ) {
+                $placeHolder.addClass( 'element-invisible' );
+                $statusBar.show();
+            }
+
+            addFile( file );
+            setState( 'ready' );
+            updateTotalProgress();
+        };
+
+        uploader.onFileDequeued = function( file ) {
+            fileCount--;
+            fileSize -= file.size;
+
+            if ( !fileCount ) {
+                setState( 'pedding' );
+            }
+
+            removeFile( file );
+            updateTotalProgress();
+
+        };
+
+        uploader.on( 'all', function( type ) {
+            var stats;
+            switch( type ) {
+                case 'uploadFinished':
+                    setState( 'confirm' );
+                    break;
+
+                case 'startUpload':
+                    setState( 'uploading' );
+                    break;
+
+                case 'stopUpload':
+                    setState( 'paused' );
+                    break;
+
+            }
+        });
+
+        uploader.onError = function( code ) {
+            alert( 'Eroor: ' + code );
+        };
+
+        $upload.on('click', function() {
+            if ( $(this).hasClass( 'disabled' ) ) {
+                return false;
+            }
+
+            if ( state === 'ready' ) {
+                uploader.upload();
+            } else if ( state === 'paused' ) {
+                uploader.upload();
+            } else if ( state === 'uploading' ) {
+                uploader.stop();
+            }
+        });
+
+        $info.on( 'click', '.retry', function() {
+            uploader.retry();
+        } );
+
+        $info.on( 'click', '.ignore', function() {
+            alert( 'todo' );
+        } );
+
+        $upload.addClass( 'state-' + state );
+        updateTotalProgress();
+    });
+});

+ 37 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/requirejs/index.html

@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <title>WebUploader演示</title>
+    <link rel="stylesheet" type="text/css" href="../../css/webuploader.css" />
+    <link rel="stylesheet" type="text/css" href="../../examples/image-upload/style.css" />
+</head>
+
+
+<body>
+    <div id="wrapper">
+        <div id="container">
+            <!--头部,相册选择和格式选择-->
+
+            <div id="uploader">
+                <div class="queueList">
+                    <div id="dndArea" class="placeholder">
+                        <div id="filePicker"></div>
+                        <p>或将照片拖到这里,单次最多可选300张</p>
+                    </div>
+                </div>
+                <div class="statusBar" style="display:none;">
+                    <div class="progress">
+                        <span class="text">0%</span>
+                        <span class="percentage"></span>
+                    </div><div class="info"></div>
+                    <div class="btns">
+                        <div id="filePicker2"></div><div class="uploadBtn">开始上传</div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <script src="./require.js" data-main="app.js"></script>
+</body>
+</html>

File diff suppressed because it is too large
+ 36 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/requirejs/require.js


+ 4 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/server/crossdomain.xml

@@ -0,0 +1,4 @@
+<?xml version="1.0" ?>
+<cross-domain-policy>
+<allow-access-from domain="*" />
+</cross-domain-policy>

+ 177 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/server/fileupload.php

@@ -0,0 +1,177 @@
+<?php
+/**
+ * upload.php
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+#!! 注意
+#!! 此文件只是个示例,不要用于真正的产品之中。
+#!! 不保证代码安全性。
+
+#!! IMPORTANT:
+#!! this file is just an example, it doesn't incorporate any security checks and
+#!! is not recommended to be used in production environment as it is. Be sure to
+#!! revise it and customize to your needs.
+
+
+// Make sure file is not cached (as it happens for example on iOS devices)
+header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
+header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+header("Cache-Control: no-store, no-cache, must-revalidate");
+header("Cache-Control: post-check=0, pre-check=0", false);
+header("Pragma: no-cache");
+
+
+// Support CORS
+// header("Access-Control-Allow-Origin: *");
+// other CORS headers if any...
+if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
+    exit; // finish preflight CORS requests here
+}
+
+
+if ( !empty($_REQUEST[ 'debug' ]) ) {
+    $random = rand(0, intval($_REQUEST[ 'debug' ]) );
+    if ( $random === 0 ) {
+        header("HTTP/1.0 500 Internal Server Error");
+        exit;
+    }
+}
+
+// header("HTTP/1.0 500 Internal Server Error");
+// exit;
+
+
+// 5 minutes execution time
+@set_time_limit(5 * 60);
+
+// Uncomment this one to fake upload time
+// usleep(5000);
+
+// Settings
+// $targetDir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
+$targetDir = 'upload_tmp';
+$uploadDir = 'upload';
+
+$cleanupTargetDir = true; // Remove old files
+$maxFileAge = 5 * 3600; // Temp file age in seconds
+
+
+// Create target dir
+if (!file_exists($targetDir)) {
+    @mkdir($targetDir);
+}
+
+// Create target dir
+if (!file_exists($uploadDir)) {
+    @mkdir($uploadDir);
+}
+
+// Get a file name
+if (isset($_REQUEST["name"])) {
+    $fileName = $_REQUEST["name"];
+} elseif (!empty($_FILES)) {
+    $fileName = $_FILES["file"]["name"];
+} else {
+    $fileName = uniqid("file_");
+}
+
+$filePath = $targetDir . DIRECTORY_SEPARATOR . $fileName;
+$uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $fileName;
+
+// Chunking might be enabled
+$chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
+$chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 1;
+
+
+// Remove old temp files
+if ($cleanupTargetDir) {
+    if (!is_dir($targetDir) || !$dir = opendir($targetDir)) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
+    }
+
+    while (($file = readdir($dir)) !== false) {
+        $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;
+
+        // If temp file is current file proceed to the next
+        if ($tmpfilePath == "{$filePath}_{$chunk}.part" || $tmpfilePath == "{$filePath}_{$chunk}.parttmp") {
+            continue;
+        }
+
+        // Remove temp file if it is older than the max age and is not the current file
+        if (preg_match('/\.(part|parttmp)$/', $file) && (@filemtime($tmpfilePath) < time() - $maxFileAge)) {
+            @unlink($tmpfilePath);
+        }
+    }
+    closedir($dir);
+}
+
+
+// Open temp file
+if (!$out = @fopen("{$filePath}_{$chunk}.parttmp", "wb")) {
+    die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
+}
+
+if (!empty($_FILES)) {
+    if ($_FILES["file"]["error"] || !is_uploaded_file($_FILES["file"]["tmp_name"])) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
+    }
+
+    // Read binary input stream and append it to temp file
+    if (!$in = @fopen($_FILES["file"]["tmp_name"], "rb")) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+    }
+} else {
+    if (!$in = @fopen("php://input", "rb")) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+    }
+}
+
+while ($buff = fread($in, 4096)) {
+    fwrite($out, $buff);
+}
+
+@fclose($out);
+@fclose($in);
+
+rename("{$filePath}_{$chunk}.parttmp", "{$filePath}_{$chunk}.part");
+
+$index = 0;
+$done = true;
+for( $index = 0; $index < $chunks; $index++ ) {
+    if ( !file_exists("{$filePath}_{$index}.part") ) {
+        $done = false;
+        break;
+    }
+}
+if ( $done ) {
+    if (!$out = @fopen($uploadPath, "wb")) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
+    }
+
+    if ( flock($out, LOCK_EX) ) {
+        for( $index = 0; $index < $chunks; $index++ ) {
+            if (!$in = @fopen("{$filePath}_{$index}.part", "rb")) {
+                break;
+            }
+
+            while ($buff = fread($in, 4096)) {
+                fwrite($out, $buff);
+            }
+
+            @fclose($in);
+            @unlink("{$filePath}_{$index}.part");
+        }
+
+        flock($out, LOCK_UN);
+    }
+    @fclose($out);
+}
+
+// Return Success JSON-RPC response
+die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');

+ 172 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/server/fileupload2.php

@@ -0,0 +1,172 @@
+<?php
+/**
+ * upload.php
+ *
+ * Copyright 2013, Moxiecode Systems AB
+ * Released under GPL License.
+ *
+ * License: http://www.plupload.com/license
+ * Contributing: http://www.plupload.com/contributing
+ */
+
+#!! IMPORTANT:
+#!! this file is just an example, it doesn't incorporate any security checks and
+#!! is not recommended to be used in production environment as it is. Be sure to
+#!! revise it and customize to your needs.
+
+
+// Make sure file is not cached (as it happens for example on iOS devices)
+header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
+header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
+header("Cache-Control: no-store, no-cache, must-revalidate");
+header("Cache-Control: post-check=0, pre-check=0", false);
+header("Pragma: no-cache");
+
+// header("HTTP/1.0 500 Internal Server Error");
+
+// echo mymd5('upload/C程序设计语言.pdf'); die;
+// Support CORS
+// header("Access-Control-Allow-Origin: *");
+// other CORS headers if any...
+if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
+    exit; // finish preflight CORS requests here
+}
+
+
+if ( !empty($_REQUEST[ 'debug' ]) ) {
+    $random = rand(0, intval($_REQUEST[ 'debug' ]) );
+    if ( $random === 0 ) {
+        header("HTTP/1.0 500 Internal Server Error");
+        exit;
+    }
+}
+
+
+// 5 minutes execution time
+@set_time_limit(5 * 60);
+
+// Uncomment this one to fake upload time
+// usleep(5000);
+
+// Settings
+// $targetDir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
+$targetDir = 'upload_tmp';
+$uploadDir = 'upload';
+
+$cleanupTargetDir = true; // Remove old files
+$maxFileAge = 5 * 3600; // Temp file age in seconds
+
+
+// Create target dir
+if (!file_exists($targetDir)) {
+    @mkdir($targetDir);
+}
+
+// Create target dir
+if (!file_exists($uploadDir)) {
+    @mkdir($uploadDir);
+}
+
+// Get a file name
+if (isset($_REQUEST["name"])) {
+    $fileName = $_REQUEST["name"];
+} elseif (!empty($_FILES)) {
+    $fileName = $_FILES["file"]["name"];
+} else {
+    $fileName = uniqid("file_");
+}
+
+$md5File = @file('md5list2.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+$md5File = $md5File ? $md5File : array();
+
+if (isset($_REQUEST["md5"]) && array_search($_REQUEST["md5"], $md5File ) !== FALSE ) {
+    die('{"jsonrpc" : "2.0", "result" : null, "id" : "id", "exist": 1}');
+}
+
+$filePath = $targetDir . DIRECTORY_SEPARATOR . $fileName;
+$uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $fileName;
+
+// Chunking might be enabled
+$chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
+$chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 0;
+
+
+// Remove old temp files
+if ($cleanupTargetDir) {
+    if (!is_dir($targetDir) || !$dir = opendir($targetDir)) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
+    }
+
+    while (($file = readdir($dir)) !== false) {
+        $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;
+
+        // If temp file is current file proceed to the next
+        if ($tmpfilePath == "{$filePath}.part") {
+            continue;
+        }
+
+        // Remove temp file if it is older than the max age and is not the current file
+        if (preg_match('/\.part$/', $file) && (filemtime($tmpfilePath) < time() - $maxFileAge)) {
+            @unlink($tmpfilePath);
+        }
+    }
+    closedir($dir);
+}
+
+
+// Open temp file
+if (!$out = @fopen("{$filePath}.part", $chunks ? "ab" : "wb")) {
+    die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
+}
+
+if (!empty($_FILES)) {
+    if ($_FILES["file"]["error"] || !is_uploaded_file($_FILES["file"]["tmp_name"])) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
+    }
+
+    // Read binary input stream and append it to temp file
+    if (!$in = @fopen($_FILES["file"]["tmp_name"], "rb")) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+    }
+} else {
+    if (!$in = @fopen("php://input", "rb")) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
+    }
+}
+
+while ($buff = fread($in, 4096)) {
+    fwrite($out, $buff);
+}
+
+@fclose($out);
+@fclose($in);
+
+// Check if file has been uploaded
+if (!$chunks || $chunk == $chunks - 1) {
+    // Strip the temp .part suffix off
+    rename("{$filePath}.part", $filePath);
+
+    rename($filePath, $uploadPath);
+    array_push($md5File, mymd5($uploadPath));
+    $md5File = array_unique($md5File);
+    file_put_contents('md5list2.txt', join($md5File, "\n"));
+}
+
+function mymd5( $file ) {
+    $fragment = 65536;
+
+    $rh = fopen($file, 'rb');
+    $size = filesize($file);
+
+    $part1 = fread( $rh, $fragment );
+    fseek($rh, $size-$fragment);
+    $part2 = fread( $rh, $fragment);
+    fclose($rh);
+
+    return md5( $part1.$part2 );
+}
+
+
+
+// Return Success JSON-RPC response
+die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');

+ 63 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/server/preview.php

@@ -0,0 +1,63 @@
+<?php
+/**
+ * 此页面用来协助 IE6/7 预览图片,因为 IE 6/7 不支持 base64
+ */
+
+$DIR = 'preview';
+// Create target dir
+if (!file_exists($DIR)) {
+    @mkdir($DIR);
+}
+
+$cleanupTargetDir = true; // Remove old files
+$maxFileAge = 5 * 3600; // Temp file age in seconds
+
+if ($cleanupTargetDir) {
+    if (!is_dir($DIR) || !$dir = opendir($DIR)) {
+        die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
+    }
+
+    while (($file = readdir($dir)) !== false) {
+        $tmpfilePath = $DIR . DIRECTORY_SEPARATOR . $file;
+
+        // Remove temp file if it is older than the max age and is not the current file
+        if (@filemtime($tmpfilePath) < time() - $maxFileAge) {
+            @unlink($tmpfilePath);
+        }
+    }
+    closedir($dir);
+}
+
+$src = file_get_contents('php://input');
+
+if (preg_match("#^data:image/(\w+);base64,(.*)$#", $src, $matches)) {
+
+    $previewUrl = sprintf(
+        "%s://%s%s",
+        isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http',
+        $_SERVER['HTTP_HOST'],
+        $_SERVER['REQUEST_URI']
+    );
+    $previewUrl = str_replace("preview.php", "", $previewUrl);
+
+
+    $base64 = $matches[2];
+    $type = $matches[1];
+    if ($type === 'jpeg') {
+        $type = 'jpg';
+    }
+
+    $filename = md5($base64).".$type";
+    $filePath = $DIR.DIRECTORY_SEPARATOR.$filename;
+
+    if (file_exists($filePath)) {
+        die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}');
+    } else {
+        $data = base64_decode($base64);
+        file_put_contents($filePath, $data);
+        die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}');
+    }
+
+} else {
+    die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "un recoginized source"}}');
+}

File diff suppressed because it is too large
+ 95 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.css


File diff suppressed because it is too large
+ 6502 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.custom.js


File diff suppressed because it is too large
+ 2 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.custom.min.js


File diff suppressed because it is too large
+ 8083 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.fis.js


File diff suppressed because it is too large
+ 4622 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.flashonly.js


File diff suppressed because it is too large
+ 2 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.flashonly.min.js


File diff suppressed because it is too large
+ 6030 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.html5only.js


File diff suppressed because it is too large
+ 2 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.html5only.min.js


File diff suppressed because it is too large
+ 8106 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.js


File diff suppressed because it is too large
+ 3 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.min.js


File diff suppressed because it is too large
+ 5026 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.noimage.js


File diff suppressed because it is too large
+ 2 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.noimage.min.js


File diff suppressed because it is too large
+ 8012 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.nolog.js


File diff suppressed because it is too large
+ 3 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.nolog.min.js


File diff suppressed because it is too large
+ 4993 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.withoutimage.js


File diff suppressed because it is too large
+ 2 - 0
watero-wechat-web/src/main/webapp/common/lib/webuploader/0.1.5/webuploader.withoutimage.min.js