├── .gitignore ├── .bowerrc ├── .eslintrc.js ├── example ├── demo.js └── demo.html ├── package.json ├── gulpfile.js ├── README.md ├── scss └── upload.scss ├── .scss-lint.yml ├── upload.vue └── upload.css /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /.idea 3 | -------------------------------------------------------------------------------- /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory" : "vendor/bower" 3 | } 4 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "browser": true, 4 | "commonjs": true, 5 | "es6": true 6 | }, 7 | "extends": "eslint:recommended", 8 | "parserOptions": { 9 | "sourceType": "module" 10 | }, 11 | "rules": { 12 | "indent": [ 13 | "error", 14 | "tab" 15 | ], 16 | "linebreak-style": [ 17 | "error", 18 | "windows" 19 | ], 20 | "quotes": [ 21 | "error", 22 | "single" 23 | ], 24 | "semi": [ 25 | "error", 26 | "always" 27 | ] 28 | } 29 | }; -------------------------------------------------------------------------------- /example/demo.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | import Vue from 'vue'; 3 | import myUpload from '../upload.vue'; 4 | 5 | 6 | new Vue({ 7 | el: '#app', 8 | data: { 9 | show1: false, 10 | show2: false, 11 | otherParams: { 12 | token: '123456798', 13 | name: 'img' 14 | } 15 | }, 16 | components: { 17 | 'my-upload': myUpload 18 | }, 19 | methods: { 20 | toggleShow1() { 21 | this.show1 = !this.show1; 22 | }, 23 | toggleShow2() { 24 | this.show2 = !this.show2; 25 | } 26 | }, 27 | events: { 28 | uploadSuccess(data, field, key){ 29 | console.log('-------- 上传成功 --------'); 30 | console.log(data); 31 | console.log('field: ' + field); 32 | console.log('key: ' + key); 33 | }, 34 | uploadFail(status, field, key){ 35 | console.log('-------- 上传失败 --------'); 36 | console.log(status); 37 | console.log('field: ' + field); 38 | console.log('key: ' + key); 39 | } 40 | } 41 | }); 42 | -------------------------------------------------------------------------------- /example/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | demo 7 | 8 | 47 | 48 | 49 | 50 |
51 |
52 | 上传图片 53 | 61 |
62 |
63 | Upload 64 | 73 |
74 |
75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-upload-file", 3 | "version": "1.1.0", 4 | "description": "A file upload component for vue. (vue文件上传组件)", 5 | "main": "upload.vue", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/dai-siki/vue-upload-file.git" 12 | }, 13 | "keywords": [ 14 | "vue-file-upload", 15 | "vue-upload", 16 | "vue-uploader", 17 | "vue-image-upload", 18 | "图片上传", 19 | "文件上传" 20 | ], 21 | "author": "dai-siki", 22 | "license": "ISC", 23 | "bugs": { 24 | "url": "https://github.com/dai-siki/vue-upload-file/issues" 25 | }, 26 | "homepage": "https://github.com/dai-siki/vue-upload-file#readme", 27 | "dependencies": { 28 | "babel-runtime": "^6.11.6" 29 | }, 30 | "devDependencies": { 31 | "babel": "^6.5.2", 32 | "babel-core": "^6.17.0", 33 | "babel-loader": "^6.2.5", 34 | "babel-plugin-transform-runtime": "^6.15.0", 35 | "babel-polyfill": "^6.16.0", 36 | "babel-preset-es2015": "^6.16.0", 37 | "babel-preset-stage-2": "^6.17.0", 38 | "babel-preset-stage-3": "^6.17.0", 39 | "browser-sync": "^2.13.0", 40 | "classnames": "^2.2.5", 41 | "css-loader": "^0.23.1", 42 | "gulp": "^3.8.8", 43 | "gulp-autoprefixer": "^3.1.1", 44 | "gulp-changed": "^1.3.0", 45 | "gulp-load-plugins": "^1.2.4", 46 | "gulp-plumber": "^1.1.0", 47 | "gulp-sass": "^2.3.2", 48 | "gulp-uglify": "^2.0.0", 49 | "gulp-util": "^3.0.7", 50 | "gulp-watch": "^4.3.6", 51 | "gulp.spritesmith": "^6.2.1", 52 | "html-webpack-plugin": "^2.22.0", 53 | "node-sass": "^3.8.0", 54 | "sass-loader": "^4.0.0", 55 | "scss": "^0.2.4", 56 | "scss-loader": "^0.0.1", 57 | "style-loader": "^0.13.1", 58 | "vinyl-named": "^1.1.0", 59 | "vue": "^1.0.28", 60 | "vue-html-loader": "^1.2.3", 61 | "vue-loader": "^8.5.4", 62 | "vue-style-loader": "^1.0.0", 63 | "webpack": "^1.13.1", 64 | "webpack-stream": "^3.2.0" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | /****************************************************** 2 | * ----前端工程自动化构建---- * 3 | * * 4 | * @author dai-siki同学 < 851733175@qq.com > * 5 | ******************************************************/ 6 | 7 | // import package 8 | const $ = require('gulp-load-plugins')(), 9 | webpack = require('webpack-stream'), 10 | named = require('vinyl-named'), 11 | browserSync = require('browser-sync').create(), 12 | reload = browserSync.reload, 13 | gulp = require('gulp'); 14 | 15 | /** 开发 16 | -------------------------------------------------------------*/ 17 | 18 | gulp.task('css', function() { 19 | gulp.src('./scss/*.scss').pipe($.sass()).pipe($.autoprefixer('last 10 version')).pipe(gulp.dest('./')); 20 | }); 21 | 22 | // jS task 23 | gulp.task('js', function() { 24 | var webpack_config = { 25 | module: { 26 | loaders: [ 27 | { 28 | test: /\.js$/, 29 | exclude: /(node_modules|bower_components)/, 30 | loader: 'babel', 31 | query: { 32 | presets: [ 33 | 'es2015', 'stage-3' 34 | ], 35 | plugins: ['transform-runtime'] 36 | } 37 | }, { 38 | test: /\.css$/, 39 | loaders: ['style', 'css'] 40 | }, { 41 | test: /\.json$/, 42 | loaders: ['json'] 43 | }, { 44 | test: /\.(scss|sass)$/, 45 | loaders: ['style', 'sass'] 46 | }, { 47 | test: /\.(html|tpl)$/, 48 | loaders: ['html'] 49 | }, { 50 | test: /\.vue$/, 51 | loaders: ['vue'] 52 | } 53 | ] 54 | } 55 | }; 56 | 57 | gulp.src('./example/demo.js').pipe($.plumber({errorHandler: _errrHandler})).pipe(named(function() { 58 | return 'demo-src'; 59 | })).pipe(webpack(webpack_config))/*.pipe($.uglify())*/.pipe(gulp.dest('./example')); 60 | }); 61 | 62 | gulp.task('serve', function() { 63 | browserSync.init({ 64 | server: { 65 | baseDir: './' 66 | } 67 | }); 68 | gulp.watch([ 69 | './example/demo.js', './*.vue', './*.css' 70 | ], ['js']); 71 | gulp.watch(['./scss/*.scss'], ['css']); 72 | gulp.watch([ 73 | './example/**/*.html', './example/demo-src.js' 74 | ], function() { 75 | reload(); 76 | }); 77 | }); 78 | 79 | gulp.task('default', ['serve']); 80 | 81 | /** 辅助函数 82 | -------------------------------------------------------------*/ 83 | //错误提示 84 | function _errrHandler(e) { 85 | $.util.beep(); 86 | $.util.log(e); 87 | } 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-upload-file 2 | 3 | A file upload component for vue. (vue文件上传组件) 4 | 5 | 6 | ## Change log (更新日志) 7 | #### @1.1.0 8 | - 多语言支持 {langType: zh/en} 9 | - 调整了Props命名 【otherParams => params, langConf => langExt】 10 | 11 | 12 | ## Demo(示例) 13 | [Click me (点我)](http://dai-siki.github.io/vue-upload-file/example/demo.html). 14 | 15 | 16 | ## Brower compatibility(浏览器兼容) 17 | IE10+ 18 | 19 | 20 | ## Env(配置环境) 21 | vue@1.0 + webpack + es6 22 | 23 | 24 | ## Install(安装) 25 | #### npm 26 | ```shell 27 | $ npm install vue-upload-file 28 | ``` 29 | 30 | 31 | ## Usage(使用) 32 | #### Props(参数) 33 | | 名称 | 类型 | 默认 | 说明 | 34 | | ----------------| ---------------- | ---------------| ------------------------------------------| 35 | | field | String | 'upload' | 域,上传文件name,触发事件会带上(如果一个页面多个图片上传控件,可以做区分 | 36 | | key | | 0 | 类似于id,触发事件会带上(如果一个页面多个图片上传控件,可以做区分 | 37 | | value | Boolean | | 是否显示控件 | 38 | | url | String | '' | 上传地址 | 39 | | params | Object | null | 要附带的其他数据,如 {k:v} | 40 | | maxSize | Number | 2048 | 单文件大小限制(kb) | 41 | | onlyImg | Boolean | false | 仅限图片 | 42 | | onlySingle | Boolean | false | 仅限单文件上传 | 43 | | langType | String | 'zh' | zh/en 语言类型 | 44 | | langExt | Object | | 语言包扩展 | 45 | 46 | #### Language Package(语言包) 47 | ```js 48 | { 49 | zh: { 50 | hint: '点击,或将文件拖动至此处', 51 | loading: '正在上传……', 52 | noSupported: '浏览器不支持该功能,请使用IE10以上或其他现代浏览器!', 53 | success: '上传成功', 54 | fail: '上传失败', 55 | error: { 56 | onlyImg: '仅限图片格式', 57 | onlySingle: '仅限单文件上传', 58 | outOfSize: '单文件大小不能超过 ', 59 | } 60 | }, 61 | en: { 62 | hint: 'Click, or drag the file here', 63 | loading: 'Uploading……', 64 | noSupported: 'Browser does not support, please use IE10+ or other browsers', 65 | success: 'Upload success', 66 | fail: 'Upload failed', 67 | error: { 68 | onlyImg: 'Images only', 69 | onlySingle: 'Single file only', 70 | outOfSize: 'File exceeds size limit: ' 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | #### Example(使用示例) 77 | ```html 78 | 83 | 84 |
85 | 上传图片 86 | 95 |
96 | 97 | 150 | ``` 151 | -------------------------------------------------------------------------------- /scss/upload.scss: -------------------------------------------------------------------------------- 1 | $i_c: #999; 2 | $i_w: 32px; 3 | $i_h: 32px; 4 | $c_succ: #4a7; 5 | $c_warn: #cc0; 6 | $c_error: #d10; 7 | @keyframes vue_upload_progress { 8 | 0% { 9 | background-position: 0 0; 10 | } 11 | 12 | 100% { 13 | background-position: 10px 0; 14 | } 15 | } 16 | @keyframes vue_upload { 17 | 0% { 18 | opacity: 0; 19 | transform: scale(0) translatey(-60px); 20 | } 21 | 22 | 100% { 23 | opacity: 1; 24 | transform: scale(1) translatey(0); 25 | } 26 | } 27 | 28 | .vue-upload-file { 29 | position: absolute; 30 | display: block; 31 | box-sizing: border-box; 32 | z-index: 999; 33 | left: 50%; 34 | margin-top: 12px; 35 | margin-left: -140px; 36 | padding: 12px 16px; 37 | width: 280px; 38 | background-color: #fff; 39 | box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); 40 | border-top: 2px solid rgba(0, 0, 0, 0.8); 41 | animation: vue_upload 0.15s ease-in; 42 | 43 | &::before { 44 | position: absolute; 45 | content: ''; 46 | top: -8px; 47 | left: 132px; 48 | width: 0; 49 | height: 0; 50 | border-bottom: 7px solid rgba(0, 0, 0, 0.8); 51 | border-left: 7px solid transparent; 52 | border-right: 7px solid transparent; 53 | } 54 | 55 | .vuf-drop-area { 56 | position: relative; 57 | padding: 10px; 58 | height: 60px; 59 | background-color: rgba(0, 0, 0, 0.03); 60 | text-align: center; 61 | border: 1px dashed #ddd; 62 | 63 | // 上传图标 64 | .vuf-icon1 { 65 | display: block; 66 | margin: 0 auto 6px; 67 | width: $i_w; 68 | height: $i_h; 69 | overflow: hidden; 70 | 71 | .vuf-icon1-arrow { 72 | display: block; 73 | margin: 0 auto; 74 | width: 0; 75 | height: 0; 76 | border-bottom: $i_h * 0.35 solid $i_c; 77 | border-left: $i_h * 0.35 solid transparent; 78 | border-right: $i_h * 0.35 solid transparent; 79 | } 80 | 81 | .vuf-icon1-body { 82 | display: block; 83 | width: $i_w * 0.3; 84 | height: $i_h * 0.35; 85 | margin: 0 auto; 86 | background-color: $i_c; 87 | } 88 | 89 | .vuf-icon1-bottom { 90 | box-sizing: border-box; 91 | display: block; 92 | height: $i_h * 0.3; 93 | border: 5px solid $i_c; 94 | border-top: none; 95 | } 96 | } 97 | 98 | .vuf-hint { 99 | font-size: 14px; 100 | color: #999; 101 | line-height: 30px; 102 | } 103 | 104 | .vuf-loading { 105 | font-size: 16px; 106 | color: #999; 107 | line-height: 30px; 108 | } 109 | 110 | .vuf-progress-wrap { 111 | display: block; 112 | background-color: rgba(#000, 0.14); 113 | 114 | .vuf-progress { 115 | position: relative; 116 | margin-top: 12px; 117 | display: block; 118 | height: 3px; 119 | background-color: $c_succ; 120 | box-shadow: 0 1px 3px 0 rgba($c_succ, 0.3); 121 | transition: width 0.5s ease; 122 | background-image: linear-gradient(-45deg, rgba(#fff, 0.2) 25%, transparent 25%, transparent 50%, rgba(#fff, 0.2) 50%, rgba(#fff, 0.2) 75%, transparent 75%, transparent); 123 | background-size: 10px 10px; 124 | animation: vue_upload_progress 0.3s linear infinite; 125 | 126 | &::after { 127 | content: ''; 128 | position: absolute; 129 | display: block; 130 | top: -2px; 131 | right: -2px; 132 | width: 5px; 133 | height: 5px; 134 | border: 1px solid rgba(#fff, 0.6); 135 | box-shadow: 0 1px 4px 0 rgba($c_succ, 0.7); 136 | border-radius: 100%; 137 | background-color: $c_succ; 138 | } 139 | } 140 | } 141 | 142 | .vuf-no-supported-hint { 143 | display: block; 144 | position: absolute; 145 | top: 0; 146 | left: 0; 147 | padding: 10px 0; 148 | width: 100%; 149 | height: 60px; 150 | line-height: 30px; 151 | background-color: #eee; 152 | text-align: center; 153 | color: #888; 154 | font-size: 14px; 155 | } 156 | 157 | &:hover { 158 | cursor: pointer; 159 | border-color: #ccc; 160 | background-color: rgba(0, 0, 0, 0.06); 161 | 162 | .vuf-hint { 163 | color: #777; 164 | } 165 | } 166 | } 167 | 168 | .vuf-error, 169 | .vuf-success { 170 | display: block; 171 | font-size: 14px; 172 | line-height: 24px; 173 | height: 24px; 174 | color: $c_error; 175 | text-align: center; 176 | vertical-align: top; 177 | } 178 | 179 | .vuf-success { 180 | color: $c_succ; 181 | } 182 | 183 | // 成功图标 184 | .vuf-icon3 { 185 | position: relative; 186 | display: inline-block; 187 | width: 20px; 188 | height: 20px; 189 | top: 4px; 190 | 191 | &::after { 192 | position: absolute; 193 | top: 3px; 194 | left: 6px; 195 | width: 6px; 196 | height: 10px; 197 | border-width: 0 2px 2px 0; 198 | border-color: $c_succ; 199 | border-style: solid; 200 | transform: rotate(45deg); 201 | content: ''; 202 | } 203 | } 204 | 205 | // 错误图标 206 | .vuf-icon2 { 207 | position: relative; 208 | display: inline-block; 209 | width: 20px; 210 | height: 20px; 211 | top: 4px; 212 | 213 | &::after, 214 | &::before { 215 | content: ''; 216 | position: absolute; 217 | top: 9px; 218 | left: 4px; 219 | width: 13px; 220 | height: 2px; 221 | background-color: $c_error; 222 | transform: rotate(45deg); 223 | } 224 | 225 | &::after { 226 | transform: rotate(-45deg); 227 | } 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /.scss-lint.yml: -------------------------------------------------------------------------------- 1 | # Default application configuration that all configurations inherit from. 2 | 3 | scss_files: "**/*.scss" 4 | plugin_directories: ['.scss-linters'] 5 | 6 | # List of gem names to load custom linters from (make sure they are already 7 | # installed) 8 | plugin_gems: [] 9 | 10 | # Default severity of all linters. 11 | severity: warning 12 | 13 | linters: 14 | BangFormat: 15 | enabled: true 16 | space_before_bang: true 17 | space_after_bang: false 18 | 19 | BemDepth: 20 | enabled: false 21 | max_elements: 1 22 | 23 | BorderZero: 24 | enabled: true 25 | convention: none # or `zero` 26 | 27 | ChainedClasses: 28 | enabled: false 29 | 30 | ColorKeyword: 31 | enabled: true 32 | 33 | ColorVariable: 34 | enabled: false 35 | 36 | Comment: 37 | enabled: false 38 | style: silent 39 | 40 | DebugStatement: 41 | enabled: true 42 | 43 | DeclarationOrder: 44 | enabled: true 45 | 46 | DisableLinterReason: 47 | enabled: false 48 | 49 | DuplicateProperty: 50 | enabled: true 51 | 52 | ElsePlacement: 53 | enabled: true 54 | style: same_line # or 'new_line' 55 | 56 | EmptyLineBetweenBlocks: 57 | enabled: true 58 | ignore_single_line_blocks: true 59 | 60 | EmptyRule: 61 | enabled: true 62 | 63 | ExtendDirective: 64 | enabled: false 65 | 66 | FinalNewline: 67 | enabled: true 68 | present: true 69 | 70 | HexLength: 71 | enabled: true 72 | style: short # or 'long' 73 | 74 | HexNotation: 75 | enabled: false 76 | style: uppercase # or 'lowercase' 77 | 78 | HexValidation: 79 | enabled: true 80 | 81 | IdSelector: 82 | enabled: true 83 | 84 | ImportantRule: 85 | enabled: false 86 | 87 | ImportPath: 88 | enabled: true 89 | leading_underscore: false 90 | filename_extension: false 91 | 92 | Indentation: 93 | enabled: true 94 | allow_non_nested_indentation: false 95 | character: tab # or 'space' 96 | width: 1 97 | 98 | LeadingZero: 99 | enabled: true 100 | style: include_zero # or 'exclude_zero' 101 | 102 | MergeableSelector: 103 | enabled: true 104 | force_nesting: true 105 | 106 | NameFormat: 107 | enabled: true 108 | allow_leading_underscore: true 109 | convention: snake_case # or 'camel_case', or 'hyphenated_lowercase', or a regex pattern 110 | 111 | NestingDepth: 112 | enabled: false 113 | max_depth: 8 114 | ignore_parent_selectors: false 115 | 116 | PlaceholderInExtend: 117 | enabled: false 118 | 119 | PrivateNamingConvention: 120 | enabled: false 121 | prefix: _ 122 | 123 | PropertyCount: 124 | enabled: false 125 | include_nested: false 126 | max_properties: 10 127 | 128 | PropertySortOrder: 129 | enabled: false 130 | ignore_unspecified: false 131 | min_properties: 2 132 | separate_groups: false 133 | 134 | PropertySpelling: 135 | enabled: true 136 | extra_properties: [] 137 | disabled_properties: [] 138 | 139 | PropertyUnits: 140 | enabled: true 141 | global: [ 142 | 'ch', 'em', 'ex', 'rem', # Font-relative lengths 143 | 'cm', 'in', 'mm', 'pc', 'pt', 'px', 'q', # Absolute lengths 144 | 'vh', 'vw', 'vmin', 'vmax', # Viewport-percentage lengths 145 | 'deg', 'grad', 'rad', 'turn', # Angle 146 | 'ms', 's', # Duration 147 | 'Hz', 'kHz', # Frequency 148 | 'dpi', 'dpcm', 'dppx', # Resolution 149 | '%'] # Other 150 | properties: {} 151 | 152 | PseudoElement: 153 | enabled: true 154 | 155 | QualifyingElement: 156 | enabled: true 157 | allow_element_with_attribute: true 158 | allow_element_with_class: false 159 | allow_element_with_id: false 160 | 161 | SelectorDepth: 162 | enabled: false 163 | max_depth: 8 164 | 165 | SelectorFormat: 166 | enabled: true 167 | convention: hyphenated_lowercase # or 'strict_BEM', or 'hyphenated_BEM', or 'snake_case', or 'camel_case', or a regex pattern 168 | 169 | Shorthand: 170 | enabled: true 171 | allowed_shorthands: [1, 2, 3, 4] 172 | 173 | SingleLinePerProperty: 174 | enabled: true 175 | allow_single_line_rule_sets: true 176 | 177 | SingleLinePerSelector: 178 | enabled: true 179 | 180 | SpaceAfterComma: 181 | enabled: true 182 | style: one_space # or 'no_space', or 'at_least_one_space' 183 | 184 | SpaceAfterComment: 185 | enabled: false 186 | style: one_space # or 'no_space', or 'at_least_one_space' 187 | allow_empty_comments: true 188 | 189 | SpaceAfterPropertyColon: 190 | enabled: true 191 | style: one_space # or 'no_space', or 'at_least_one_space', or 'aligned' 192 | 193 | SpaceAfterPropertyName: 194 | enabled: true 195 | 196 | SpaceAfterVariableColon: 197 | enabled: false 198 | style: one_space # or 'no_space', 'at_least_one_space' or 'one_space_or_newline' 199 | 200 | SpaceAfterVariableName: 201 | enabled: true 202 | 203 | SpaceAroundOperator: 204 | enabled: true 205 | style: one_space # or 'at_least_one_space', or 'no_space' 206 | 207 | SpaceBeforeBrace: 208 | enabled: true 209 | style: space # or 'new_line' 210 | allow_single_line_padding: false 211 | 212 | SpaceBetweenParens: 213 | enabled: true 214 | spaces: 0 215 | 216 | StringQuotes: 217 | enabled: true 218 | style: single_quotes # or double_quotes 219 | 220 | TrailingSemicolon: 221 | enabled: true 222 | 223 | TrailingWhitespace: 224 | enabled: true 225 | 226 | TrailingZero: 227 | enabled: false 228 | 229 | TransitionAll: 230 | enabled: false 231 | 232 | UnnecessaryMantissa: 233 | enabled: true 234 | 235 | UnnecessaryParentReference: 236 | enabled: true 237 | 238 | UrlFormat: 239 | enabled: true 240 | 241 | UrlQuotes: 242 | enabled: true 243 | 244 | VariableForProperty: 245 | enabled: false 246 | properties: [] 247 | 248 | VendorPrefix: 249 | enabled: true 250 | identifier_list: base 251 | additional_identifiers: [] 252 | excluded_identifiers: [] 253 | 254 | ZeroUnit: 255 | enabled: true 256 | 257 | Compass::*: 258 | enabled: false 259 | -------------------------------------------------------------------------------- /upload.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 285 | 286 | 287 | -------------------------------------------------------------------------------- /upload.css: -------------------------------------------------------------------------------- 1 | @-webkit-keyframes vue_upload_progress { 2 | 0% { 3 | background-position: 0 0; } 4 | 100% { 5 | background-position: 10px 0; } } 6 | 7 | @keyframes vue_upload_progress { 8 | 0% { 9 | background-position: 0 0; } 10 | 100% { 11 | background-position: 10px 0; } } 12 | 13 | @-webkit-keyframes vue_upload { 14 | 0% { 15 | opacity: 0; 16 | -webkit-transform: scale(0) translatey(-60px); 17 | transform: scale(0) translatey(-60px); } 18 | 100% { 19 | opacity: 1; 20 | -webkit-transform: scale(1) translatey(0); 21 | transform: scale(1) translatey(0); } } 22 | 23 | @keyframes vue_upload { 24 | 0% { 25 | opacity: 0; 26 | -webkit-transform: scale(0) translatey(-60px); 27 | transform: scale(0) translatey(-60px); } 28 | 100% { 29 | opacity: 1; 30 | -webkit-transform: scale(1) translatey(0); 31 | transform: scale(1) translatey(0); } } 32 | 33 | .vue-upload-file { 34 | position: absolute; 35 | display: block; 36 | -webkit-box-sizing: border-box; 37 | box-sizing: border-box; 38 | z-index: 999; 39 | left: 50%; 40 | margin-top: 12px; 41 | margin-left: -140px; 42 | padding: 12px 16px; 43 | width: 280px; 44 | background-color: #fff; 45 | -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); 46 | box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18); 47 | border-top: 2px solid rgba(0, 0, 0, 0.8); 48 | -webkit-animation: vue_upload 0.15s ease-in; 49 | animation: vue_upload 0.15s ease-in; } 50 | .vue-upload-file::before { 51 | position: absolute; 52 | content: ''; 53 | top: -8px; 54 | left: 132px; 55 | width: 0; 56 | height: 0; 57 | border-bottom: 7px solid rgba(0, 0, 0, 0.8); 58 | border-left: 7px solid transparent; 59 | border-right: 7px solid transparent; } 60 | .vue-upload-file .vuf-drop-area { 61 | position: relative; 62 | padding: 10px; 63 | height: 60px; 64 | background-color: rgba(0, 0, 0, 0.03); 65 | text-align: center; 66 | border: 1px dashed #ddd; } 67 | .vue-upload-file .vuf-drop-area .vuf-icon1 { 68 | display: block; 69 | margin: 0 auto 6px; 70 | width: 32px; 71 | height: 32px; 72 | overflow: hidden; } 73 | .vue-upload-file .vuf-drop-area .vuf-icon1 .vuf-icon1-arrow { 74 | display: block; 75 | margin: 0 auto; 76 | width: 0; 77 | height: 0; 78 | border-bottom: 11.2px solid #999; 79 | border-left: 11.2px solid transparent; 80 | border-right: 11.2px solid transparent; } 81 | .vue-upload-file .vuf-drop-area .vuf-icon1 .vuf-icon1-body { 82 | display: block; 83 | width: 9.6px; 84 | height: 11.2px; 85 | margin: 0 auto; 86 | background-color: #999; } 87 | .vue-upload-file .vuf-drop-area .vuf-icon1 .vuf-icon1-bottom { 88 | -webkit-box-sizing: border-box; 89 | box-sizing: border-box; 90 | display: block; 91 | height: 9.6px; 92 | border: 5px solid #999; 93 | border-top: none; } 94 | .vue-upload-file .vuf-drop-area .vuf-hint { 95 | font-size: 14px; 96 | color: #999; 97 | line-height: 30px; } 98 | .vue-upload-file .vuf-drop-area .vuf-loading { 99 | font-size: 16px; 100 | color: #999; 101 | line-height: 30px; } 102 | .vue-upload-file .vuf-drop-area .vuf-progress-wrap { 103 | display: block; 104 | background-color: rgba(0, 0, 0, 0.14); } 105 | .vue-upload-file .vuf-drop-area .vuf-progress-wrap .vuf-progress { 106 | position: relative; 107 | margin-top: 12px; 108 | display: block; 109 | height: 3px; 110 | background-color: #4a7; 111 | -webkit-box-shadow: 0 1px 3px 0 rgba(68, 170, 119, 0.3); 112 | box-shadow: 0 1px 3px 0 rgba(68, 170, 119, 0.3); 113 | -webkit-transition: width 0.5s ease; 114 | transition: width 0.5s ease; 115 | background-image: -webkit-linear-gradient(135deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); 116 | background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent); 117 | background-size: 10px 10px; 118 | -webkit-animation: vue_upload_progress 0.3s linear infinite; 119 | animation: vue_upload_progress 0.3s linear infinite; } 120 | .vue-upload-file .vuf-drop-area .vuf-progress-wrap .vuf-progress::after { 121 | content: ''; 122 | position: absolute; 123 | display: block; 124 | top: -2px; 125 | right: -2px; 126 | width: 5px; 127 | height: 5px; 128 | border: 1px solid rgba(255, 255, 255, 0.6); 129 | -webkit-box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7); 130 | box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7); 131 | border-radius: 100%; 132 | background-color: #4a7; } 133 | .vue-upload-file .vuf-drop-area .vuf-no-supported-hint { 134 | display: block; 135 | position: absolute; 136 | top: 0; 137 | left: 0; 138 | padding: 10px 0; 139 | width: 100%; 140 | height: 60px; 141 | line-height: 30px; 142 | background-color: #eee; 143 | text-align: center; 144 | color: #888; 145 | font-size: 14px; } 146 | .vue-upload-file .vuf-drop-area:hover { 147 | cursor: pointer; 148 | border-color: #ccc; 149 | background-color: rgba(0, 0, 0, 0.06); } 150 | .vue-upload-file .vuf-drop-area:hover .vuf-hint { 151 | color: #777; } 152 | .vue-upload-file .vuf-error, 153 | .vue-upload-file .vuf-success { 154 | display: block; 155 | font-size: 14px; 156 | line-height: 24px; 157 | height: 24px; 158 | color: #d10; 159 | text-align: center; 160 | vertical-align: top; } 161 | .vue-upload-file .vuf-success { 162 | color: #4a7; } 163 | .vue-upload-file .vuf-icon3 { 164 | position: relative; 165 | display: inline-block; 166 | width: 20px; 167 | height: 20px; 168 | top: 4px; } 169 | .vue-upload-file .vuf-icon3::after { 170 | position: absolute; 171 | top: 3px; 172 | left: 6px; 173 | width: 6px; 174 | height: 10px; 175 | border-width: 0 2px 2px 0; 176 | border-color: #4a7; 177 | border-style: solid; 178 | -webkit-transform: rotate(45deg); 179 | -ms-transform: rotate(45deg); 180 | transform: rotate(45deg); 181 | content: ''; } 182 | .vue-upload-file .vuf-icon2 { 183 | position: relative; 184 | display: inline-block; 185 | width: 20px; 186 | height: 20px; 187 | top: 4px; } 188 | .vue-upload-file .vuf-icon2::after, .vue-upload-file .vuf-icon2::before { 189 | content: ''; 190 | position: absolute; 191 | top: 9px; 192 | left: 4px; 193 | width: 13px; 194 | height: 2px; 195 | background-color: #d10; 196 | -webkit-transform: rotate(45deg); 197 | -ms-transform: rotate(45deg); 198 | transform: rotate(45deg); } 199 | .vue-upload-file .vuf-icon2::after { 200 | -webkit-transform: rotate(-45deg); 201 | -ms-transform: rotate(-45deg); 202 | transform: rotate(-45deg); } 203 | --------------------------------------------------------------------------------