zpj hace 1 año
commit
9502d48beb
Se han modificado 100 ficheros con 7655 adiciones y 0 borrados
  1. 14 0
      .editorconfig
  2. 5 0
      .env.development
  3. 6 0
      .env.production
  4. 8 0
      .env.staging
  5. 4 0
      .eslintignore
  6. 201 0
      .eslintrc.js
  7. 18 0
      .gitignore
  8. 5 0
      .travis.yml
  9. 21 0
      LICENSE
  10. 111 0
      README-zh.md
  11. 99 0
      README.md
  12. 14 0
      babel.config.js
  13. 35 0
      build/index.js
  14. 678 0
      cv.tex
  15. 24 0
      jest.config.js
  16. 9 0
      jsconfig.json
  17. 88 0
      package.json
  18. 8 0
      postcss.config.js
  19. 40 0
      public/Ueditor/dialogs/anchor/anchor.html
  20. 681 0
      public/Ueditor/dialogs/attachment/attachment.css
  21. 60 0
      public/Ueditor/dialogs/attachment/attachment.html
  22. 754 0
      public/Ueditor/dialogs/attachment/attachment.js
  23. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_chm.gif
  24. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_default.png
  25. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_doc.gif
  26. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_exe.gif
  27. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_jpg.gif
  28. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_mp3.gif
  29. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_mv.gif
  30. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_pdf.gif
  31. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_ppt.gif
  32. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_psd.gif
  33. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_rar.gif
  34. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_txt.gif
  35. BIN
      public/Ueditor/dialogs/attachment/fileTypeImages/icon_xls.gif
  36. BIN
      public/Ueditor/dialogs/attachment/images/alignicon.gif
  37. BIN
      public/Ueditor/dialogs/attachment/images/alignicon.png
  38. BIN
      public/Ueditor/dialogs/attachment/images/bg.png
  39. BIN
      public/Ueditor/dialogs/attachment/images/file-icons.gif
  40. BIN
      public/Ueditor/dialogs/attachment/images/file-icons.png
  41. BIN
      public/Ueditor/dialogs/attachment/images/icons.gif
  42. BIN
      public/Ueditor/dialogs/attachment/images/icons.png
  43. BIN
      public/Ueditor/dialogs/attachment/images/image.png
  44. BIN
      public/Ueditor/dialogs/attachment/images/progress.png
  45. BIN
      public/Ueditor/dialogs/attachment/images/success.gif
  46. BIN
      public/Ueditor/dialogs/attachment/images/success.png
  47. 94 0
      public/Ueditor/dialogs/background/background.css
  48. 56 0
      public/Ueditor/dialogs/background/background.html
  49. 376 0
      public/Ueditor/dialogs/background/background.js
  50. BIN
      public/Ueditor/dialogs/background/images/bg.png
  51. BIN
      public/Ueditor/dialogs/background/images/success.png
  52. 65 0
      public/Ueditor/dialogs/charts/chart.config.js
  53. 165 0
      public/Ueditor/dialogs/charts/charts.css
  54. 89 0
      public/Ueditor/dialogs/charts/charts.html
  55. 519 0
      public/Ueditor/dialogs/charts/charts.js
  56. BIN
      public/Ueditor/dialogs/charts/images/charts0.png
  57. BIN
      public/Ueditor/dialogs/charts/images/charts1.png
  58. BIN
      public/Ueditor/dialogs/charts/images/charts2.png
  59. BIN
      public/Ueditor/dialogs/charts/images/charts3.png
  60. BIN
      public/Ueditor/dialogs/charts/images/charts4.png
  61. BIN
      public/Ueditor/dialogs/charts/images/charts5.png
  62. 43 0
      public/Ueditor/dialogs/emotion/emotion.css
  63. 54 0
      public/Ueditor/dialogs/emotion/emotion.html
  64. 186 0
      public/Ueditor/dialogs/emotion/emotion.js
  65. BIN
      public/Ueditor/dialogs/emotion/images/0.gif
  66. BIN
      public/Ueditor/dialogs/emotion/images/bface.gif
  67. BIN
      public/Ueditor/dialogs/emotion/images/cface.gif
  68. BIN
      public/Ueditor/dialogs/emotion/images/fface.gif
  69. BIN
      public/Ueditor/dialogs/emotion/images/jxface2.gif
  70. BIN
      public/Ueditor/dialogs/emotion/images/neweditor-tab-bg.png
  71. BIN
      public/Ueditor/dialogs/emotion/images/tface.gif
  72. BIN
      public/Ueditor/dialogs/emotion/images/wface.gif
  73. BIN
      public/Ueditor/dialogs/emotion/images/yface.gif
  74. 89 0
      public/Ueditor/dialogs/gmap/gmap.html
  75. 7 0
      public/Ueditor/dialogs/help/help.css
  76. 82 0
      public/Ueditor/dialogs/help/help.html
  77. 56 0
      public/Ueditor/dialogs/help/help.js
  78. 894 0
      public/Ueditor/dialogs/image/image.css
  79. 120 0
      public/Ueditor/dialogs/image/image.html
  80. 1025 0
      public/Ueditor/dialogs/image/image.js
  81. BIN
      public/Ueditor/dialogs/image/images/alignicon.jpg
  82. BIN
      public/Ueditor/dialogs/image/images/bg.png
  83. BIN
      public/Ueditor/dialogs/image/images/icons.gif
  84. BIN
      public/Ueditor/dialogs/image/images/icons.png
  85. BIN
      public/Ueditor/dialogs/image/images/image.png
  86. BIN
      public/Ueditor/dialogs/image/images/progress.png
  87. BIN
      public/Ueditor/dialogs/image/images/success.gif
  88. BIN
      public/Ueditor/dialogs/image/images/success.png
  89. 98 0
      public/Ueditor/dialogs/insertframe/insertframe.html
  90. 81 0
      public/Ueditor/dialogs/internal.js
  91. 126 0
      public/Ueditor/dialogs/link/link.html
  92. 135 0
      public/Ueditor/dialogs/map/map.html
  93. 118 0
      public/Ueditor/dialogs/map/show.html
  94. 30 0
      public/Ueditor/dialogs/music/music.css
  95. 32 0
      public/Ueditor/dialogs/music/music.html
  96. 192 0
      public/Ueditor/dialogs/music/music.js
  97. 40 0
      public/Ueditor/dialogs/preview/preview.html
  98. BIN
      public/Ueditor/dialogs/scrawl/images/addimg.png
  99. BIN
      public/Ueditor/dialogs/scrawl/images/brush.png
  100. BIN
      public/Ueditor/dialogs/scrawl/images/delimg.png

+ 14 - 0
.editorconfig

@@ -0,0 +1,14 @@
+# http://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+insert_final_newline = false
+trim_trailing_whitespace = false

+ 5 - 0
.env.development

@@ -0,0 +1,5 @@
+# just a flag
+ENV = 'development'
+
+# base api
+VUE_APP_BASE_API = '/adminApi/'

+ 6 - 0
.env.production

@@ -0,0 +1,6 @@
+# just a flag
+ENV = 'production'
+
+# base api
+VUE_APP_BASE_API = '/adminApi/'
+

+ 8 - 0
.env.staging

@@ -0,0 +1,8 @@
+NODE_ENV = production
+
+# just a flag
+ENV = 'staging'
+
+# base api
+VUE_APP_BASE_API = '/adminApi/'
+

+ 4 - 0
.eslintignore

@@ -0,0 +1,4 @@
+build/*.js
+src/assets
+public
+dist

+ 201 - 0
.eslintrc.js

@@ -0,0 +1,201 @@
+module.exports = {
+  root: true,
+  parserOptions: {
+    parser: 'babel-eslint',
+    sourceType: 'module'
+  },
+  env: {
+    browser: true,
+    node: true,
+    es6: true,
+  },
+  extends: [
+    'plugin:vue/recommended',
+    'eslint:recommended'
+  ],
+
+  // add your custom rules here
+  //it is base on https://github.com/vuejs/eslint-config-vue
+  rules: {
+    "vue/max-attributes-per-line": [2, {
+      "singleline": 10,
+      "multiline": {
+        "max": 1,
+        "allowFirstLine": false
+      }
+    }],
+    "vue/singleline-html-element-content-newline": "off",
+    "vue/multiline-html-element-content-newline":"off",
+    "vue/name-property-casing": ["error", "PascalCase"],
+    "vue/no-v-html": "off",
+    'accessor-pairs': 2,
+    'arrow-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'block-spacing': [2, 'always'],
+    'brace-style': [2, '1tbs', {
+      'allowSingleLine': true
+    }],
+    'camelcase': [0, {
+      'properties': 'always'
+    }],
+    'comma-dangle': [2, 'never'],
+    'comma-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'comma-style': [2, 'last'],
+    'constructor-super': 2,
+    'curly': [2, 'multi-line'],
+    'dot-location': [2, 'property'],
+    'eol-last': 2,
+    'eqeqeq': ["error", "always", {"null": "ignore"}],
+    'generator-star-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'handle-callback-err': [2, '^(err|error)$'],
+    'indent': [2, 2, {
+      'SwitchCase': 1
+    }],
+    'jsx-quotes': [2, 'prefer-single'],
+    'key-spacing': [2, {
+      'beforeColon': false,
+      'afterColon': true
+    }],
+    'keyword-spacing': [2, {
+      'before': true,
+      'after': true
+    }],
+    'new-cap': [2, {
+      'newIsCap': true,
+      'capIsNew': false
+    }],
+    'new-parens': 2,
+    'no-array-constructor': 2,
+    'no-caller': 2,
+    'no-console': 'off',
+    'no-class-assign': 2,
+    'no-cond-assign': 2,
+    'no-const-assign': 2,
+    'no-control-regex': 0,
+    'no-delete-var': 2,
+    'no-dupe-args': 2,
+    'no-dupe-class-members': 2,
+    'no-dupe-keys': 2,
+    'no-duplicate-case': 2,
+    'no-empty-character-class': 2,
+    'no-empty-pattern': 2,
+    'no-eval': 2,
+    'no-ex-assign': 2,
+    'no-extend-native': 2,
+    'no-extra-bind': 2,
+    'no-extra-boolean-cast': 2,
+    'no-extra-parens': [2, 'functions'],
+    'no-fallthrough': 2,
+    'no-floating-decimal': 2,
+    'no-func-assign': 2,
+    'no-implied-eval': 2,
+    'no-inner-declarations': [2, 'functions'],
+    'no-invalid-regexp': 2,
+    'no-irregular-whitespace': 2,
+    'no-iterator': 2,
+    'no-label-var': 2,
+    'no-labels': [2, {
+      'allowLoop': false,
+      'allowSwitch': false
+    }],
+    'no-lone-blocks': 2,
+    'no-mixed-spaces-and-tabs': 2,
+    'no-multi-spaces': 2,
+    'no-multi-str': 2,
+    'no-multiple-empty-lines': [2, {
+      'max': 1
+    }],
+    'no-native-reassign': 2,
+    'no-negated-in-lhs': 2,
+    'no-new-object': 2,
+    'no-new-require': 2,
+    'no-new-symbol': 2,
+    'no-new-wrappers': 2,
+    'no-obj-calls': 2,
+    'no-octal': 2,
+    'no-octal-escape': 2,
+    'no-path-concat': 2,
+    'no-proto': 2,
+    'no-redeclare': 2,
+    'no-regex-spaces': 2,
+    'no-return-assign': [2, 'except-parens'],
+    'no-self-assign': 2,
+    'no-self-compare': 2,
+    'no-sequences': 2,
+    'no-shadow-restricted-names': 2,
+    'no-spaced-func': 2,
+    'no-sparse-arrays': 2,
+    'no-this-before-super': 2,
+    'no-throw-literal': 2,
+    'no-trailing-spaces': 2,
+    'no-undef': 2,
+    'no-undef-init': 2,
+    'no-unexpected-multiline': 2,
+    'no-unmodified-loop-condition': 2,
+    'no-unneeded-ternary': [2, {
+      'defaultAssignment': false
+    }],
+    'no-unreachable': 2,
+    'no-unsafe-finally': 2,
+    'no-unused-vars': [2, {
+      'vars': 'all',
+      'args': 'none'
+    }],
+    'no-useless-call': 2,
+    'no-useless-computed-key': 2,
+    'no-useless-constructor': 2,
+    'no-useless-escape': 0,
+    'no-whitespace-before-property': 2,
+    'no-with': 2,
+    'one-var': [2, {
+      'initialized': 'never'
+    }],
+    'operator-linebreak': [2, 'after', {
+      'overrides': {
+        '?': 'before',
+        ':': 'before'
+      }
+    }],
+    'padded-blocks': [2, 'never'],
+    'quotes': [2, 'single', {
+      'avoidEscape': true,
+      'allowTemplateLiterals': true
+    }],
+    'semi': [2, 'never'],
+    'semi-spacing': [2, {
+      'before': false,
+      'after': true
+    }],
+    'space-before-blocks': [2, 'always'],
+    'space-before-function-paren': [2, 'never'],
+    'space-in-parens': [2, 'never'],
+    'space-infix-ops': 2,
+    'space-unary-ops': [2, {
+      'words': true,
+      'nonwords': false
+    }],
+    'spaced-comment': [2, 'always', {
+      'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ',']
+    }],
+    'template-curly-spacing': [2, 'never'],
+    'use-isnan': 2,
+    'valid-typeof': 2,
+    'wrap-iife': [2, 'any'],
+    'yield-star-spacing': [2, 'both'],
+    'yoda': [2, 'never'],
+    'prefer-const': 2,
+    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
+    'object-curly-spacing': [2, 'always', {
+      objectsInObjects: false
+    }],
+    'array-bracket-spacing': [2, 'never']
+  }
+}

+ 18 - 0
.gitignore

@@ -0,0 +1,18 @@
+.DS_Store
+node_modules/
+dist/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+package-lock.json
+tests/**/coverage/
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+src/views/goodsManage/time.html
+aaaaaaaaaaaaa.txt

+ 5 - 0
.travis.yml

@@ -0,0 +1,5 @@
+language: node_js
+node_js: 10
+script: npm run test
+notifications:
+  email: false

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017-present PanJiaChen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 111 - 0
README-zh.md

@@ -0,0 +1,111 @@
+# vue-admin-template
+
+> 这是一个极简的 vue admin 管理后台。它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。
+
+[线上地址](http://panjiachen.github.io/vue-admin-template)
+
+[国内访问](https://panjiachen.gitee.io/vue-admin-template)
+
+目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0),它不依赖 `vue-cli`。
+
+<p align="center">
+  <b>SPONSORED BY</b>
+</p>
+<p align="center">
+   <a href="https://finclip.com?from=vue_element" title="FinClip" target="_blank">
+      <img height="200px" src="https://gitee.com/panjiachen/gitee-cdn/raw/master/vue%E8%B5%9E%E5%8A%A9.png" title="FinClip">
+   </a>
+</p>
+
+## Extra
+
+如果你想要根据用户角色来动态生成侧边栏和 router,你可以使用该分支[permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
+
+## 相关项目
+
+- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
+
+- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
+
+- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
+
+- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
+
+写了一个系列的教程配套文章,如何从零构建后一个完整的后台项目:
+
+- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
+- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
+- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
+- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板,专门针对本项目的文章,算作是一篇文档)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
+- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
+
+## Build Setup
+
+```bash
+# 克隆项目
+git clone https://github.com/PanJiaChen/vue-admin-template.git
+
+# 进入项目目录
+cd vue-admin-template
+
+# 安装依赖
+npm install
+
+# 建议不要直接使用 cnpm 安装以来,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
+npm install --registry=https://registry.npm.taobao.org
+
+# 启动服务
+npm run dev
+```
+
+浏览器访问 [http://localhost:9528](http://localhost:9528)
+
+## 发布
+
+```bash
+# 构建测试环境
+npm run build:stage
+
+# 构建生产环境
+npm run build:prod
+```
+
+## 其它
+
+```bash
+# 预览发布环境效果
+npm run preview
+
+# 预览发布环境效果 + 静态资源分析
+npm run preview -- --report
+
+# 代码格式检查
+npm run lint
+
+# 代码格式检查并自动修复
+npm run lint -- --fix
+```
+
+更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
+
+## 购买贴纸
+
+你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,我们将获得 2 元的捐赠。
+
+## Demo
+
+![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
+
+## Browsers support
+
+Modern browsers and Internet Explorer 10+.
+
+| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
+| --------- | --------- | --------- | --------- |
+| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
+
+## License
+
+[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
+
+Copyright (c) 2017-present PanJiaChen

+ 99 - 0
README.md

@@ -0,0 +1,99 @@
+# vue-admin-template
+
+English | [简体中文](./README-zh.md)
+
+> A minimal vue admin template with Element UI & axios & iconfont & permission control & lint
+
+**Live demo:** http://panjiachen.github.io/vue-admin-template
+
+
+**The current version is `v4.0+` build on `vue-cli`. If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-admin-template/tree/tag/3.11.0), it does not rely on `vue-cli`**
+
+<p align="center">
+  <b>SPONSORED BY</b>
+</p>
+<p align="center">
+   <a href="https://finclip.com?from=vue_element" title="FinClip" target="_blank">
+      <img height="200px" src="https://gitee.com/panjiachen/gitee-cdn/raw/master/vue%E8%B5%9E%E5%8A%A9.png" title="FinClip">
+   </a>
+</p>
+
+## Build Setup
+
+```bash
+# clone the project
+git clone https://github.com/PanJiaChen/vue-admin-template.git
+
+# enter the project directory
+cd vue-admin-template
+
+# install dependency
+npm install
+
+# develop
+npm run dev
+```
+
+This will automatically open http://localhost:9528
+
+## Build
+
+```bash
+# build for test environment
+npm run build:stage
+
+# build for production environment
+npm run build:prod
+```
+
+## Advanced
+
+```bash
+# preview the release environment effect
+npm run preview
+
+# preview the release environment effect + static resource analysis
+npm run preview -- --report
+
+# code format check
+npm run lint
+
+# code format check and auto fix
+npm run lint -- --fix
+```
+
+Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
+
+## Demo
+
+![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif)
+
+## Extra
+
+If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control)
+
+For `typescript` version, you can use [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
+
+## Related Project
+
+- [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
+
+- [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
+
+- [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template)
+
+- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
+
+## Browsers support
+
+Modern browsers and Internet Explorer 10+.
+
+| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
+| --------- | --------- | --------- | --------- |
+| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
+
+## License
+
+[MIT](https://github.com/PanJiaChen/vue-admin-template/blob/master/LICENSE) license.
+
+Copyright (c) 2017-present PanJiaChen

+ 14 - 0
babel.config.js

@@ -0,0 +1,14 @@
+module.exports = {
+  presets: [
+    // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
+    '@vue/cli-plugin-babel/preset'
+  ],
+  'env': {
+    'development': {
+      // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
+      // This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
+      // https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
+      'plugins': ['dynamic-import-node']
+    }
+  }
+}

+ 35 - 0
build/index.js

@@ -0,0 +1,35 @@
+const { run } = require('runjs')
+const chalk = require('chalk')
+const config = require('../vue.config.js')
+const rawArgv = process.argv.slice(2)
+const args = rawArgv.join(' ')
+
+if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
+  const report = rawArgv.includes('--report')
+
+  run(`vue-cli-service build ${args}`)
+
+  const port = 9526
+  const publicPath = config.publicPath
+
+  var connect = require('connect')
+  var serveStatic = require('serve-static')
+  const app = connect()
+
+  app.use(
+    publicPath,
+    serveStatic('./dist', {
+      index: ['index.html', '/']
+    })
+  )
+
+  app.listen(port, function () {
+    console.log(chalk.green(`> Preview at  http://localhost:${port}${publicPath}`))
+    if (report) {
+      console.log(chalk.green(`> Report at  http://localhost:${port}${publicPath}report.html`))
+    }
+
+  })
+} else {
+  run(`vue-cli-service build ${args}`)
+}

+ 678 - 0
cv.tex

@@ -0,0 +1,678 @@
+
+%-----------------------------------------------------------------------------------------------------------------------------------------------%
+%	The MIT License (MIT)
+%
+%	Copyright (c) 2019 Jan Küster
+%
+%	Permission is hereby granted, free of charge, to any person obtaining a copy
+%	of this software and associated documentation files (the "Software"), to deal
+%	in the Software without restriction, including without limitation the rights
+%	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+%	copies of the Software, and to permit persons to whom the Software is
+%	furnished to do so, subject to the following conditions:
+%	
+%	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+%	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+%	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+%	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+%	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+%	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+%	THE SOFTWARE.
+%	
+%
+%-----------------------------------------------------------------------------------------------------------------------------------------------%
+
+
+%============================================================================%
+%
+%	DOCUMENT DEFINITION
+%
+%============================================================================%
+
+\documentclass[10pt,A4,english]{article}	
+
+
+%----------------------------------------------------------------------------------------
+%	ENCODING
+%----------------------------------------------------------------------------------------
+
+% we use utf8 since we want to build from any machine
+\usepackage[utf8]{inputenc}		
+\usepackage[USenglish]{isodate}
+\usepackage{fancyhdr}
+\usepackage[numbers]{natbib}
+
+%----------------------------------------------------------------------------------------
+%	LOGIC
+%----------------------------------------------------------------------------------------
+
+% provides \isempty test
+\usepackage{xstring, xifthen}
+\usepackage{enumitem}
+\usepackage[english]{babel}
+\usepackage{blindtext}
+\usepackage{pdfpages}
+\usepackage{changepage}
+%----------------------------------------------------------------------------------------
+%	FONT BASICS
+%----------------------------------------------------------------------------------------
+
+% some tex-live fonts - choose your own
+
+%\usepackage[defaultsans]{droidsans}
+%\usepackage[default]{comfortaa}
+%\usepackage{cmbright}
+\usepackage[default]{raleway}
+%\usepackage{fetamont}
+%\usepackage[default]{gillius}
+%\usepackage[light,math]{iwona}
+%\usepackage[thin]{roboto} 
+
+% set font default
+\renewcommand*\familydefault{\sfdefault} 	
+\usepackage[T1]{fontenc}
+
+% more font size definitions
+\usepackage{moresize}
+
+%----------------------------------------------------------------------------------------
+%	FONT AWESOME ICONS
+%---------------------------------------------------------------------------------------- 
+
+% include the fontawesome icon set
+\usepackage{fontawesome}
+
+% use to vertically center content
+% credits to: http://tex.stackexchange.com/questions/7219/how-to-vertically-center-two-images-next-to-each-other
+\newcommand{\vcenteredinclude}[1]{\begingroup
+\setbox0=\hbox{\includegraphics{#1}}%
+\parbox{\wd0}{\box0}\endgroup}
+\newcommand{\tab}[1]{\hspace{.2\textwidth}\rlap{#1}}
+% use to vertically center content
+% credits to: http://tex.stackexchange.com/questions/7219/how-to-vertically-center-two-images-next-to-each-other
+\newcommand*{\vcenteredhbox}[1]{\begingroup
+\setbox0=\hbox{#1}\parbox{\wd0}{\box0}\endgroup}
+
+% icon shortcut
+\newcommand{\icon}[3] { 							
+	\makebox(#2, #2){\textcolor{maincol}{\csname fa#1\endcsname}}
+}	
+
+
+% icon with text shortcut
+\newcommand{\icontext}[4]{ 						
+	\vcenteredhbox{\icon{#1}{#2}{#3}}  \hspace{2pt}  \parbox{0.9\mpwidth}{\textcolor{#4}{#3}}
+}
+
+% icon with website url
+\newcommand{\iconhref}[5]{ 						
+    \vcenteredhbox{\icon{#1}{#2}{#5}}  \hspace{2pt} \href{#4}{\textcolor{#5}{#3}}
+}
+
+% icon with email link
+\newcommand{\iconemail}[5]{ 						
+    \vcenteredhbox{\icon{#1}{#2}{#5}}  \hspace{2pt} \href{mailto:#4}{\textcolor{#5}{#3}}
+}
+
+%----------------------------------------------------------------------------------------
+%	PAGE LAYOUT  DEFINITIONS
+%----------------------------------------------------------------------------------------
+
+% page outer frames (debug-only)
+% \usepackage{showframe}		
+
+% we use paracol to display breakable two columns
+\usepackage{paracol}
+\usepackage{tikzpagenodes}
+\usetikzlibrary{calc}
+\usepackage{lmodern}
+\usepackage{multicol}
+\usepackage{lipsum}
+\usepackage{atbegshi}
+% define page styles using geometry
+\usepackage[a4paper]{geometry}
+
+% remove all possible margins
+\geometry{top=1cm, bottom=1cm, left=1cm, right=1cm}
+
+\usepackage{fancyhdr}
+\pagestyle{empty}
+
+% space between header and content
+% \setlength{\headheight}{0pt}
+
+% indentation is zero
+\setlength{\parindent}{0mm}
+
+%----------------------------------------------------------------------------------------
+%	TABLE /ARRAY DEFINITIONS
+%---------------------------------------------------------------------------------------- 
+
+% extended aligning of tabular cells
+\usepackage{array}
+
+% custom column right-align with fixed width
+% use like p{size} but via x{size}
+\newcolumntype{x}[1]{%
+>{\raggedleft\hspace{0pt}}p{#1}}%
+
+
+%----------------------------------------------------------------------------------------
+%	GRAPHICS DEFINITIONS
+%---------------------------------------------------------------------------------------- 
+
+%for header image
+\usepackage{graphicx}
+
+% use this for floating figures
+% \usepackage{wrapfig}
+% \usepackage{float}
+% \floatstyle{boxed} 
+% \restylefloat{figure}
+
+%for drawing graphics		
+\usepackage{tikz}			
+\usepackage{ragged2e}	
+\usetikzlibrary{shapes, backgrounds,mindmap, trees}
+
+%----------------------------------------------------------------------------------------
+%	Color DEFINITIONS
+%---------------------------------------------------------------------------------------- 
+\usepackage{transparent}
+\usepackage{color}
+
+% primary color
+\definecolor{maincol}{RGB}{ 64,64,64}
+
+% accent color, secondary
+% \definecolor{accentcol}{RGB}{ 250, 150, 10 }
+
+% dark color
+\definecolor{darkcol}{RGB}{ 70, 70, 70 }
+
+% light color
+\definecolor{lightcol}{RGB}{245,245,245}
+
+\definecolor{accentcol}{RGB}{59,77,97}
+
+
+
+% Package for links, must be the last package used
+\usepackage[hidelinks]{hyperref}
+
+% returns minipage width minus two times \fboxsep
+% to keep padding included in width calculations
+% can also be used for other boxes / environments
+\newcommand{\mpwidth}{\linewidth-\fboxsep-\fboxsep}
+	
+
+
+%============================================================================%
+%
+%	CV COMMANDS
+%
+%============================================================================%
+
+%----------------------------------------------------------------------------------------
+%	 CV LIST
+%----------------------------------------------------------------------------------------
+
+% renders a standard latex list but abstracts away the environment definition (begin/end)
+\newcommand{\cvlist}[1] {
+	\begin{itemize}{#1}\end{itemize}
+}
+
+%----------------------------------------------------------------------------------------
+%	 CV TEXT
+%----------------------------------------------------------------------------------------
+
+% base class to wrap any text based stuff here. Renders like a paragraph.
+% Allows complex commands to be passed, too.
+% param 1: *any
+\newcommand{\cvtext}[1] {
+	\begin{tabular*}{1\mpwidth}{p{0.98\mpwidth}}
+		\parbox{1\mpwidth}{#1}
+	\end{tabular*}
+}
+\newcommand{\cvtextsmall}[1] {
+	\begin{tabular*}{0.8\mpwidth}{p{0.8\mpwidth}}
+		\parbox{0.8\mpwidth}{#1}
+	\end{tabular*}
+}
+%----------------------------------------------------------------------------------------
+%	CV SECTION
+%----------------------------------------------------------------------------------------
+
+% Renders a a CV section headline with a nice underline in main color.
+% param 1: section title
+\newlength{\barw}
+\newcommand{\cvsection}[1] {
+	\vspace{14pt}
+	\settowidth{\barw}{\textbf{\LARGE #1}}
+	\cvtext{
+		\textbf{\LARGE{\textcolor{darkcol}{#1}}}\\[-4pt]
+		\textcolor{accentcol}{ \rule{\barw}{1.5pt} } \\
+	}
+}
+
+\newcommand{\cvsubsection}[1] {
+	\vspace{14pt}
+	\settowidth{\barw}{\textbf{\Large #1}}
+	\cvtext{
+		\textbf{\Large{\textcolor{darkcol}{#1}}}\\[-4pt]
+		\textcolor{accentcol}{ \rule{\barw}{1.5pt} } \\
+	}
+}
+
+\newcommand{\cvheadline}[1] {
+	\vspace{16pt}
+	\cvtext{
+		\textbf{\Huge{\textcolor{accentcol}{#1}}}\\[-4pt]
+		 
+	}
+}
+
+\newcommand{\cvsubheadline}[1] {
+	\vspace{16pt}
+	\cvtext{
+		\textbf{\huge{\textcolor{darkcol}{#1}}}\\[-4pt]
+		 
+	}
+}
+%----------------------------------------------------------------------------------------
+%	META SKILL
+%----------------------------------------------------------------------------------------
+
+% Renders a progress-bar to indicate a certain skill in percent.
+% param 1: name of the skill / tech / etc.
+% param 2: level (for example in years)
+% param 3: percent, values range from 0 to 1
+\newcommand{\cvskill}[3] {
+	\begin{tabular*}{1\mpwidth}{p{0.72\mpwidth}  r}
+ 		\textcolor{black}{\textbf{#1}} & \textcolor{maincol}{#2}\\
+	\end{tabular*}%
+	
+	\hspace{4pt}
+	\begin{tikzpicture}[scale=1,rounded corners=2pt,very thin]
+		\fill [lightcol] (0,0) rectangle (1\mpwidth, 0.15);
+		\fill [accentcol] (0,0) rectangle (#3\mpwidth, 0.15);
+  	\end{tikzpicture}%
+}
+
+
+%----------------------------------------------------------------------------------------
+%	 CV EVENT
+%----------------------------------------------------------------------------------------
+
+% Renders a table and a paragraph (cvtext) wrapped in a parbox (to ensure minimum content
+% is glued together when a pagebreak appears).
+% Additional Information can be passed in text or list form (or other environments).
+% the work you did
+% param 1: time-frame i.e. Sep 14 - Jan 15 etc.
+% param 2:	 event name (job position etc.)
+% param 3: Customer, Employer, Industry
+% param 4: Short description
+% param 5: work done (optional)
+% param 6: technologies include (optional)
+% param 7: achievements (optional)
+\newcommand{\cvevent}[7] {
+	
+	% we wrap this part in a parbox, so title and description are not separated on a pagebreak
+	% if you need more control on page breaks, remove the parbox
+	\parbox{\mpwidth}{
+		\begin{tabular*}{1\mpwidth}{p{0.66\mpwidth}  r}
+	 		\textcolor{black}{\textbf{#2}} & \colorbox{accentcol}{\makebox[0.32\mpwidth]{\textcolor{white}{\textbf{#1}}}} \\
+			\textcolor{maincol}{#3} & \\
+		\end{tabular*}\\[8pt]
+	
+		\ifthenelse{\isempty{#4}}{}{
+			\cvtext{#4}\\
+		}
+	}
+	\vspace{14pt}
+}
+
+
+%----------------------------------------------------------------------------------------
+%	 CV META EVENT
+%----------------------------------------------------------------------------------------
+
+% Renders a CV event on the sidebar
+% param 1: title
+% param 2: subtitle (optional)
+% param 3: customer, employer, etc,. (optional)
+% param 4: info text (optional)
+\newcommand{\cvmetaevent}[4] {
+	\textcolor{maincol} { \cvtext{\textbf{\begin{flushleft}#1\end{flushleft}}}}
+
+	\ifthenelse{\isempty{#2}}{}{
+	\textcolor{black} {\cvtext{\textbf{#2}} }
+	}
+
+	\ifthenelse{\isempty{#3}}{}{
+		\cvtext{{ \textcolor{maincol} {#3} }}\\
+	}
+
+	\cvtext{#4}\\[14pt]
+}
+
+%---------------------------------------------------------------------------------------
+%	QR CODE
+%----------------------------------------------------------------------------------------
+
+% Renders a qrcode image (centered, relative to the parentwidth)
+% param 1: percent width, from 0 to 1
+\newcommand{\cvqrcode}[1] {
+	\begin{center}
+		\includegraphics[width={#1}\mpwidth]{qrcode}
+	\end{center}
+}
+
+
+% HEADER AND FOOOTER 
+%====================================
+\newcommand\Header[1]{%
+\begin{tikzpicture}[remember picture,overlay]
+\fill[accentcol]
+  (current page.north west) -- (current page.north east) --
+  ([yshift=50pt]current page.north east|-current page text area.north east) --
+  ([yshift=50pt,xshift=-3cm]current page.north|-current page text area.north) --
+  ([yshift=10pt,xshift=-5cm]current page.north|-current page text area.north) --
+  ([yshift=10pt]current page.north west|-current page text area.north west) -- cycle;
+\node[font=\sffamily\bfseries\color{white},anchor=west,
+  xshift=0.7cm,yshift=-0.32cm] at (current page.north west)
+  {\fontsize{12}{12}\selectfont {#1}};
+\end{tikzpicture}%
+}
+
+\newcommand\Footer[1]{%
+\begin{tikzpicture}[remember picture,overlay]
+\fill[lightcol]
+  (current page.south east) -- (current page.south west) --
+  ([yshift=-80pt]current page.south east|-current page text area.south east) --
+  ([yshift=-80pt,xshift=-6cm]current page.south|-current page text area.south) --
+  ([xshift=-2.5cm,yshift=-10pt]current page.south|-current page text area.south) --	
+  ([yshift=-10pt]current page.south east|-current page text area.south east) -- cycle;
+\node[yshift=0.32cm,xshift=9cm] at (current page.south) {\fontsize{10}{10}\selectfont \textbf{\thepage}};
+\end{tikzpicture}%
+}
+
+
+%=====================================
+%============================================================================%
+%
+%
+%
+%	DOCUMENT CONTENT
+%
+%
+%
+%============================================================================%
+\begin{document}
+
+\columnratio{0.31}
+\setlength{\columnsep}{2.2em}
+\setlength{\columnseprule}{4pt}
+\colseprulecolor{white}
+
+
+% LEBENSLAUF HIERE
+\AtBeginShipoutFirst{\Header{CV}\Footer{1}}
+\AtBeginShipout{\AtBeginShipoutAddToBox{\Header{CV}\Footer{2}}}
+
+\newpage
+
+\colseprulecolor{lightcol}
+\columnratio{0.31}
+\setlength{\columnsep}{2.2em}
+\setlength{\columnseprule}{4pt}
+\begin{paracol}{2}
+
+
+\begin{leftcolumn}
+%---------------------------------------------------------------------------------------
+%	META IMAGE
+%----------------------------------------------------------------------------------------
+\includegraphics[width=\linewidth]{resources/image.jpg}	%trimming relative to image size
+
+%---------------------------------------------------------------------------------------
+%	META SKILLS
+%----------------------------------------------------------------------------------------
+	\fcolorbox{white}{white}{\begin{minipage}[c][1.5cm][c]{1\mpwidth}
+		\LARGE{\textbf{\textcolor{maincol}{Philip Empl}}} \\[2pt]
+		\normalsize{ \textcolor{maincol} {Management Information Systems (M. Sc.)} }
+\end{minipage}} \\
+\icontext{CaretRight}{12}{XX.XX.XXXX in Los Angeles}{black}\\[6pt]
+\icontext{CaretRight}{12}{german}{black}\\[6pt]
+\icontext{CaretRight}{12}{unmarried}{black}\\[6pt]
+
+
+
+\cvsection{Skills}
+
+\cvskill{Software development} {6+ Jahre} {1} \\[-2pt]
+
+\cvskill{Cyber security} {4+ yrs.} {0.64} \\[-2pt]
+
+\cvskill{Internet business/ \newline E-commerce} {4+ yrs.} {0.64} \\[-2pt]
+
+\cvskill{Web development} {2+ yrs.} {0.32} \\[-2pt]
+
+\cvskill{Big data/ \newline Data science} {2+ yrs.} {0.32} \\[-2pt]
+
+\cvskill{Distributed legder \newline technology} {2+ yrs.} {0.32} \\[-2pt]
+
+\cvskill{Internet of things} {1+ yrs.} {0.16} \\[-2pt]
+
+\cvskill{Cloud computing} {1+ yrs.} {0.16} \\[-2pt] \\
+
+\cvskill{German} {L1} {1} \\[-2pt]
+
+\cvskill{English} {C1} {0.9} \\[-2pt]
+
+\newpage
+%---------------------------------------------------------------------------------------
+%	EDUCATION
+%----------------------------------------------------------------------------------------
+\cvsection{Education}
+
+\cvmetaevent
+{XX/XXXX - XX/XXXX}
+{Management Information Systems (M.Sc.)}
+{University of Lorem}
+{\textit{Field 1 • Field 2} \newline Master's thesis: \glqq title of Master's thesis\grqq.}
+\cvmetaevent
+{XX/XXXX - XX/XXXX}
+{Managment Information Systems (B.Sc.)}
+{University of Lorem}
+{\textit{Field 1 • Field 2} \newline Bachelor's thesis: \glqq title of Master's thesis\grqq.}
+
+\cvmetaevent
+{XX/XXXX - XX/XXXX}
+{A-Level}
+{High School Lorem}
+{\textit{Field 1 • Field 2 • Field 3 • Field 4 • Field 5}.}
+
+
+%
+%\cvsection{Projekte}
+
+%	\cvlist{
+%		\item \hyperlink{https://github.com/philipempl/ether-twin}{\textbf{Ether-Twin.}}\\ Ethereum Applikation für Digital Twins.
+%		\item \hyperlink{https://github.com/philipempl/Peter-Pan}{\textbf{Peter Pan.}}\\ Koch-App (t.b.a.).
+%		\item \hyperlink{https://github.com/philipempl/Innovation-Tool}{\textbf{Innovation Tool.}}\\ Webcrawler für \hyperlink{https://ibi.de/}{Ibi}.
+%		\item \hyperlink{https://github.com/philipempl/cozone}{\textbf{COZONE.}} \\ Soziales Netzwerk (t.b.a.).
+%		\item \hyperlink{https://github.com/geritwagner/enlit}{\textbf{ENLIT.}}\\ Exploring new Literature (Bachelorarbeit).
+%		\item \textbf{Crowdfunding.} \\Modul mit \hyperlink{https://senacor.com/}{Senacor} für \hyperlink{https://www.paydirekt.de/}{paydirekt}.
+%		}
+
+\cvsection{Interests}
+
+\icontext{CaretRight}{12}{Guitarist}{black}\\[6pt]
+\icontext{CaretRight}{12}{DIY}{black}\\[6pt]
+\icontext{CaretRight}{12}{Fitness}{black}\\[6pt]
+\icontext{CaretRight}{12}{Cooking}{black}\\[6pt]
+\icontext{CaretRight}{12}{Travel}{black}\\[6pt]
+
+
+
+
+\cvsection{Contact}
+
+\icontext{MapMarker}{16}{Street name XX\\D-XXXXX Lorem}{black}\\[6pt]
+\icontext{MobilePhone}{16}{+XX XXX XXXX XXXX}{black}\\[6pt]
+\iconemail{Envelope}{16}{XXXX@XXXXX.XX}{XXXX@XXXXX.XX}{black}\\[6pt]
+\iconhref{Home}{16}{XXX.XXX-XXXX.XX}{http://XXX-XXX.XXX.XX}{black}\\[6pt]
+\iconhref{Github}{16}{github.com/username}{https://www.github.com/username}{black}\\[6pt]
+\iconhref{Xing}{16}{xing.com/user\_name}{https://www.xing.com/profile/User_Name}{black}\\
+
+	
+%\cvqrcode{0.3}
+
+\end{leftcolumn}
+\begin{rightcolumn}
+%---------------------------------------------------------------------------------------
+%	TITLE  HEADER
+%----------------------------------------------------------------------------------------
+
+
+%---------------------------------------------------------------------------------------
+%	PROFILE
+%----------------------------------------------------------------------------------------
+\cvsection{Biography}
+\vspace{4pt}
+
+\cvtext{\Blindtext[1]
+
+
+
+
+}
+
+
+%---------------------------------------------------------------------------------------
+%	WORK EXPERIENCE
+%----------------------------------------------------------------------------------------
+
+\vspace{10pt}
+\cvsection{Work experience}
+\vspace{4pt}
+
+
+\cvevent
+{XX/XXXX - today}
+	{Research assistant | PhD student}
+	{Department of Lipsum (Prof. Name)\newline University of Lipsum}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+
+\cvevent
+{XX/XXXX - XX/XXXX}
+	{Part-time research assistant}
+	{Department of Lipsum (Prof. Name)\newline University of Lipsum}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+
+	
+\cvevent
+{XX/XXXX - XX/XXXX}
+	{Trainer - Course name}
+	{Department of Lipsum (Prof. Name)\newline University of Lipsum}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+
+	
+\cvevent
+    {XX/XXXX - XX/XXXX}
+	{Trainer - Course name}
+	{Department of Lipsum (Prof. Name)\newline University of Lipsum}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of ","  is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+	\vfill\null
+
+
+   	
+\cvevent
+{XX/XXXX - XX/XXXX}
+	{Trainer - Course name}
+	{Department of Lipsum (Prof. Name)\newline University of Lipsum}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+	
+\cvevent
+{XX/XXXX - XX/XXXX}
+	{Part-time research assistant}
+	{Department of Lipsum (Prof. Name)\newline University of Lipsum}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+
+
+\cvevent
+{XX/XXXX - XX/XXXX}
+	{Internship}
+	{Department \newline Company name (Location)}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+\cvevent
+{XX/XXXX - XX/XXXX}
+	{Student assistant}
+	{Department of Lipsum (Prof. Name)\newline University of Lipsum}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+
+\cvevent
+{XX/XXXX - XX/XXXX}
+	{Trainer - Course name}
+	{Department of Lipsum (Prof. Name)\newline University of Lipsum}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+
+
+\cvevent
+{XX/XXXX - XX/XXXX}
+	{Working student}
+	{Department \newline Company name (Location)}
+	{Here you can describe your work content and go into detail about individual parts of this job. Possibly an enumeration by means of "," is useful. Otherwise, describe the essential content of this item in 1-2 sentences.}
+	\vfill\null
+
+
+\cvsection{Publications}
+
+\begin{itemize}[leftmargin=*]
+\item Author, G. \& Author, P. \&  Author G. (2020). "This is the title of the publication". In: \textit{Proceedings of the 28th Conference on Lipsum (LIPSUM)}, Lipsum, June 12-17, 2020.
+\item Author, G. \& Author, P. \&  Author G. (2020). "This is the title of the publication". In: \textit{Proceedings of the 28th Conference on Lipsum (LIPSUM)}, Lipsum, June 12-17, 2020.
+\item Author, G. \& Author, P. \&  Author G. (2020). "This is the title of the publication". In: \textit{Proceedings of the 28th Conference on Lipsum (LIPSUM)}, Lipsum, June 12-17, 2020.
+\end{itemize}
+% hofixes to create fake-space to ensure the whole height is used
+\mbox{}
+\vfill
+\mbox{}
+\vfill
+\mbox{}
+\vfill
+\mbox{}
+\vfill
+\mbox{}
+\vfill
+\mbox{}
+\vfill
+\mbox{}
+
+
+Lorem, \today     \hspace{1cm}   \hrulefill
+
+\hspace*{30mm}\phantom{Lorem, \today }Philip Empl
+
+\end{rightcolumn}
+\end{paracol}
+
+
+\end{document}

+ 24 - 0
jest.config.js

@@ -0,0 +1,24 @@
+module.exports = {
+  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
+  transform: {
+    '^.+\\.vue$': 'vue-jest',
+    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
+      'jest-transform-stub',
+    '^.+\\.jsx?$': 'babel-jest'
+  },
+  moduleNameMapper: {
+    '^@/(.*)$': '<rootDir>/src/$1'
+  },
+  snapshotSerializers: ['jest-serializer-vue'],
+  testMatch: [
+    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
+  ],
+  collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
+  coverageDirectory: '<rootDir>/tests/unit/coverage',
+  // 'collectCoverage': true,
+  'coverageReporters': [
+    'lcov',
+    'text-summary'
+  ],
+  testURL: 'http://localhost/'
+}

+ 9 - 0
jsconfig.json

@@ -0,0 +1,9 @@
+{
+  "compilerOptions": {
+    "baseUrl": "./",
+    "paths": {
+        "@/*": ["src/*"]
+    }
+  },
+  "exclude": ["node_modules", "dist"]
+}

+ 88 - 0
package.json

@@ -0,0 +1,88 @@
+{
+  "name": "vue-admin-template",
+  "version": "4.4.0",
+  "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint",
+  "author": "Pan <panfree23@gmail.com>",
+  "scripts": {
+    "dev": "vue-cli-service serve",
+    "build:prod": "vue-cli-service build",
+    "build:stage": "vue-cli-service build --mode staging",
+    "preview": "node build/index.js --preview",
+    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
+    "lint": "eslint --ext .js,.vue src",
+    "test:unit": "jest --clearCache && vue-cli-service test:unit",
+    "test:ci": "npm run lint && npm run test:unit"
+  },
+  "dependencies": {
+    "@qiun/ucharts": "^2.5.0-20230101",
+    "@qiun/vue-ucharts": "2.5.0-20230101",
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "^1.0.2",
+    "@zebra-ui/swiper": "^2.2.8",
+    "af-table-column": "1.0.3",
+    "ali-oss": "6.17.1",
+    "animate.css": "^4.1.1",
+    "axios": "0.18.1",
+    "clipboard": "2.0.11",
+    "core-js": "3.33.0",
+    "cos-js-sdk-v5": "1.4.10",
+    "echarts": "5.4.0",
+    "element-ui": "^2.13.2",
+    "js-cookie": "2.2.0",
+    "latex.js": "^0.12.6",
+    "normalize.css": "7.0.0",
+    "nprogress": "0.2.0",
+    "path-to-regexp": "2.4.0",
+    "postcss-px2rem": "^0.3.0",
+    "svgdom": "^0.1.17",
+    "uuid": "^11.0.3",
+    "vue": "^2.6.10",
+    "vue-baidu-map": "0.21.22",
+    "vue-router": "3.0.6",
+    "vuedraggable": "^2.24.3",
+    "vuex": "3.1.0",
+    "wangeditor": "4.7.12",
+    "yarn": "^1.22.19"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "4.4.4",
+    "@vue/cli-plugin-eslint": "4.4.4",
+    "@vue/cli-plugin-unit-jest": "4.4.4",
+    "@vue/cli-service": "4.4.4",
+    "@vue/test-utils": "1.0.0-beta.29",
+    "autoprefixer": "9.5.1",
+    "babel-eslint": "10.1.0",
+    "babel-jest": "23.6.0",
+    "babel-plugin-dynamic-import-node": "2.3.3",
+    "chalk": "2.4.2",
+    "connect": "3.6.6",
+    "eslint": "6.7.2",
+    "eslint-plugin-vue": "6.2.2",
+    "html-webpack-plugin": "3.2.0",
+    "http-proxy-middleware": "2.0.3",
+    "less": "^2.7.2",
+    "less-loader": "^4.0.6",
+    "lib-flexible": "^0.3.2",
+    "mockjs": "1.0.1-beta3",
+    "px2rem-loader": "^0.1.9",
+    "runjs": "4.3.2",
+    "sass": "1.26.8",
+    "sass-loader": "8.0.2",
+    "script-ext-html-webpack-plugin": "2.1.3",
+    "serve-static": "1.13.2",
+    "svg-sprite-loader": "4.1.3",
+    "svgo": "1.2.2",
+    "vue-template-compiler": "^2.7.16"
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions"
+  ],
+  "engines": {
+    "node": ">=8.9",
+    "npm": ">= 3.0.0"
+  },
+  "license": "MIT",
+  "main": "index.js",
+  "repository": "http://git.lcpcp.cc/py/wh-admin.git"
+}

+ 8 - 0
postcss.config.js

@@ -0,0 +1,8 @@
+// https://github.com/michael-ciniawsky/postcss-load-config
+
+module.exports = {
+  'plugins': {
+    // to edit target browsers: use "browserslist" field in package.json
+    'autoprefixer': {}
+  }
+}

+ 40 - 0
public/Ueditor/dialogs/anchor/anchor.html

@@ -0,0 +1,40 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+    "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+        <title></title>
+        <style type="text/css">
+            *{color: #838383;margin: 0;padding: 0}
+            html,body {font-size: 12px;overflow: hidden; }
+            .content{padding:5px 0 0 15px;}
+            input{width:210px;height:21px;line-height:21px;margin-left: 4px;}
+        </style>
+    </head>
+    <body>
+        <div class="content">
+            <span><var id="lang_input_anchorName"></var></span><input id="anchorName"  value="" />
+        </div>
+        <script type="text/javascript" src="../internal.js"></script>
+        <script type="text/javascript">
+            var anchorInput = $G('anchorName'),
+                node = editor.selection.getRange().getClosedNode();
+            if(node && node.tagName == 'IMG' && (node = node.getAttribute('anchorname'))){
+                anchorInput.value = node;
+            }
+            anchorInput.onkeydown = function(evt){
+                evt = evt || window.event;
+                if(evt.keyCode == 13){
+                    editor.execCommand('anchor', anchorInput.value);
+                    dialog.close();
+                    domUtils.preventDefault(evt)
+                }
+            };
+            dialog.onok = function (){
+                editor.execCommand('anchor', anchorInput.value);
+                dialog.close();
+            };
+            $focus(anchorInput);
+        </script>
+    </body>
+</html>

+ 681 - 0
public/Ueditor/dialogs/attachment/attachment.css

@@ -0,0 +1,681 @@
+@charset "utf-8";
+/* dialog样式 */
+.wrapper {
+    zoom: 1;
+    width: 630px;
+    *width: 626px;
+    height: 380px;
+    margin: 0 auto;
+    padding: 10px;
+    position: relative;
+    font-family: sans-serif;
+}
+
+/*tab样式框大小*/
+.tabhead {
+    float:left;
+}
+.tabbody {
+    width: 100%;
+    height: 346px;
+    position: relative;
+    clear: both;
+}
+
+.tabbody .panel {
+    position: absolute;
+    width: 0;
+    height: 0;
+    background: #fff;
+    overflow: hidden;
+    display: none;
+}
+
+.tabbody .panel.focus {
+    width: 100%;
+    height: 346px;
+    display: block;
+}
+
+/* 上传附件 */
+.tabbody #upload.panel {
+    width: 0;
+    height: 0;
+    overflow: hidden;
+    position: absolute !important;
+    clip: rect(1px, 1px, 1px, 1px);
+    background: #fff;
+    display: block;
+}
+
+.tabbody #upload.panel.focus {
+    width: 100%;
+    height: 346px;
+    display: block;
+    clip: auto;
+}
+
+#upload .queueList {
+    margin: 0;
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    overflow: hidden;
+}
+
+#upload p {
+    margin: 0;
+}
+
+.element-invisible {
+    width: 0 !important;
+    height: 0 !important;
+    border: 0;
+    padding: 0;
+    margin: 0;
+    overflow: hidden;
+    position: absolute !important;
+    clip: rect(1px, 1px, 1px, 1px);
+}
+
+#upload .placeholder {
+    margin: 10px;
+    border: 2px dashed #e6e6e6;
+    *border: 0px dashed #e6e6e6;
+    height: 172px;
+    padding-top: 150px;
+    text-align: center;
+    background: url(images/image.png) center 70px no-repeat;
+    color: #cccccc;
+    font-size: 18px;
+    position: relative;
+    top:0;
+    *top: 10px;
+}
+
+#upload .placeholder .webuploader-pick {
+    font-size: 18px;
+    background: #00b7ee;
+    border-radius: 3px;
+    line-height: 44px;
+    padding: 0 30px;
+    *width: 120px;
+    color: #fff;
+    display: inline-block;
+    margin: 0 auto 20px auto;
+    cursor: pointer;
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+}
+
+#upload .placeholder .webuploader-pick-hover {
+    background: #00a2d4;
+}
+
+
+#filePickerContainer {
+    text-align: center;
+}
+
+#upload .placeholder .flashTip {
+    color: #666666;
+    font-size: 12px;
+    position: absolute;
+    width: 100%;
+    text-align: center;
+    bottom: 20px;
+}
+
+#upload .placeholder .flashTip a {
+    color: #0785d1;
+    text-decoration: none;
+}
+
+#upload .placeholder .flashTip a:hover {
+    text-decoration: underline;
+}
+
+#upload .placeholder.webuploader-dnd-over {
+    border-color: #999999;
+}
+
+#upload .filelist {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+    overflow-x: hidden;
+    overflow-y: auto;
+    position: relative;
+    height: 300px;
+}
+
+#upload .filelist:after {
+    content: '';
+    display: block;
+    width: 0;
+    height: 0;
+    overflow: hidden;
+    clear: both;
+}
+
+#upload .filelist li {
+    width: 113px;
+    height: 113px;
+    background: url(images/bg.png);
+    text-align: center;
+    margin: 9px 0 0 9px;
+    *margin: 6px 0 0 6px;
+    position: relative;
+    display: block;
+    float: left;
+    overflow: hidden;
+    font-size: 12px;
+}
+
+#upload .filelist li p.log {
+    position: relative;
+    top: -45px;
+}
+
+#upload .filelist li p.title {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    top: 5px;
+    text-indent: 5px;
+    text-align: left;
+}
+
+#upload .filelist li p.progress {
+    position: absolute;
+    width: 100%;
+    bottom: 0;
+    left: 0;
+    height: 8px;
+    overflow: hidden;
+    z-index: 50;
+    margin: 0;
+    border-radius: 0;
+    background: none;
+    -webkit-box-shadow: 0 0 0;
+}
+
+#upload .filelist li p.progress span {
+    display: none;
+    overflow: hidden;
+    width: 0;
+    height: 100%;
+    background: #1483d8 url(images/progress.png) repeat-x;
+
+    -webit-transition: width 200ms linear;
+    -moz-transition: width 200ms linear;
+    -o-transition: width 200ms linear;
+    -ms-transition: width 200ms linear;
+    transition: width 200ms linear;
+
+    -webkit-animation: progressmove 2s linear infinite;
+    -moz-animation: progressmove 2s linear infinite;
+    -o-animation: progressmove 2s linear infinite;
+    -ms-animation: progressmove 2s linear infinite;
+    animation: progressmove 2s linear infinite;
+
+    -webkit-transform: translateZ(0);
+}
+
+@-webkit-keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+@-moz-keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+@keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+#upload .filelist li p.imgWrap {
+    position: relative;
+    z-index: 2;
+    line-height: 113px;
+    vertical-align: middle;
+    overflow: hidden;
+    width: 113px;
+    height: 113px;
+
+    -webkit-transform-origin: 50% 50%;
+    -moz-transform-origin: 50% 50%;
+    -o-transform-origin: 50% 50%;
+    -ms-transform-origin: 50% 50%;
+    transform-origin: 50% 50%;
+
+    -webit-transition: 200ms ease-out;
+    -moz-transition: 200ms ease-out;
+    -o-transition: 200ms ease-out;
+    -ms-transition: 200ms ease-out;
+    transition: 200ms ease-out;
+}
+#upload .filelist li p.imgWrap.notimage {
+    margin-top: 0;
+    width: 111px;
+    height: 111px;
+    border: 1px #eeeeee solid;
+}
+#upload .filelist li p.imgWrap.notimage i.file-preview {
+    margin-top: 15px;
+}
+
+#upload .filelist li img {
+    width: 100%;
+}
+
+#upload .filelist li p.error {
+    background: #f43838;
+    color: #fff;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    height: 28px;
+    line-height: 28px;
+    width: 100%;
+    z-index: 100;
+    display:none;
+}
+
+#upload .filelist li .success {
+    display: block;
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    height: 40px;
+    width: 100%;
+    z-index: 200;
+    background: url(images/success.png) no-repeat right bottom;
+    background-image: url(images/success.gif) \9;
+}
+
+#upload .filelist li.filePickerBlock {
+    width: 113px;
+    height: 113px;
+    background: url(images/image.png) no-repeat center 12px;
+    border: 1px solid #eeeeee;
+    border-radius: 0;
+}
+#upload .filelist li.filePickerBlock div.webuploader-pick  {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    opacity: 0;
+    background: none;
+    font-size: 0;
+}
+
+#upload .filelist div.file-panel {
+    position: absolute;
+    height: 0;
+    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0;
+    background: rgba(0, 0, 0, 0.5);
+    width: 100%;
+    top: 0;
+    left: 0;
+    overflow: hidden;
+    z-index: 300;
+}
+
+#upload .filelist div.file-panel span {
+    width: 24px;
+    height: 24px;
+    display: inline;
+    float: right;
+    text-indent: -9999px;
+    overflow: hidden;
+    background: url(images/icons.png) no-repeat;
+    background: url(images/icons.gif) no-repeat \9;
+    margin: 5px 1px 1px;
+    cursor: pointer;
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+
+#upload .filelist div.file-panel span.rotateLeft {
+    display:none;
+    background-position: 0 -24px;
+}
+
+#upload .filelist div.file-panel span.rotateLeft:hover {
+    background-position: 0 0;
+}
+
+#upload .filelist div.file-panel span.rotateRight {
+    display:none;
+    background-position: -24px -24px;
+}
+
+#upload .filelist div.file-panel span.rotateRight:hover {
+    background-position: -24px 0;
+}
+
+#upload .filelist div.file-panel span.cancel {
+    background-position: -48px -24px;
+}
+
+#upload .filelist div.file-panel span.cancel:hover {
+    background-position: -48px 0;
+}
+
+#upload .statusBar {
+    height: 45px;
+    border-bottom: 1px solid #dadada;
+    margin: 0 10px;
+    padding: 0;
+    line-height: 45px;
+    vertical-align: middle;
+    position: relative;
+}
+
+#upload .statusBar .progress {
+    border: 1px solid #1483d8;
+    width: 198px;
+    background: #fff;
+    height: 18px;
+    position: absolute;
+    top: 12px;
+    display: none;
+    text-align: center;
+    line-height: 18px;
+    color: #6dbfff;
+    margin: 0 10px 0 0;
+}
+#upload .statusBar .progress span.percentage {
+    width: 0;
+    height: 100%;
+    left: 0;
+    top: 0;
+    background: #1483d8;
+    position: absolute;
+}
+#upload .statusBar .progress span.text {
+    position: relative;
+    z-index: 10;
+}
+
+#upload .statusBar .info {
+    display: inline-block;
+    font-size: 14px;
+    color: #666666;
+}
+
+#upload .statusBar .btns {
+    position: absolute;
+    top: 7px;
+    right: 0;
+    line-height: 30px;
+}
+
+#filePickerBtn {
+    display: inline-block;
+    float: left;
+}
+#upload .statusBar .btns .webuploader-pick,
+#upload .statusBar .btns .uploadBtn,
+#upload .statusBar .btns .uploadBtn.state-uploading,
+#upload .statusBar .btns .uploadBtn.state-paused {
+    background: #ffffff;
+    border: 1px solid #cfcfcf;
+    color: #565656;
+    padding: 0 18px;
+    display: inline-block;
+    border-radius: 3px;
+    margin-left: 10px;
+    cursor: pointer;
+    font-size: 14px;
+    float: left;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+#upload .statusBar .btns .webuploader-pick-hover,
+#upload .statusBar .btns .uploadBtn:hover,
+#upload .statusBar .btns .uploadBtn.state-uploading:hover,
+#upload .statusBar .btns .uploadBtn.state-paused:hover {
+    background: #f0f0f0;
+}
+
+#upload .statusBar .btns .uploadBtn,
+#upload .statusBar .btns .uploadBtn.state-paused{
+    background: #00b7ee;
+    color: #fff;
+    border-color: transparent;
+}
+#upload .statusBar .btns .uploadBtn:hover,
+#upload .statusBar .btns .uploadBtn.state-paused:hover{
+    background: #00a2d4;
+}
+
+#upload .statusBar .btns .uploadBtn.disabled {
+    pointer-events: none;
+    filter:alpha(opacity=60);
+    -moz-opacity:0.6;
+    -khtml-opacity: 0.6;
+    opacity: 0.6;
+}
+
+
+
+/* 图片管理样式 */
+#online {
+    width: 100%;
+    height: 336px;
+    padding: 10px 0 0 0;
+}
+#online #fileList{
+    width: 100%;
+    height: 100%;
+    overflow-x: hidden;
+    overflow-y: auto;
+    position: relative;
+}
+#online ul {
+    display: block;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+#online li {
+    float: left;
+    display: block;
+    list-style: none;
+    padding: 0;
+    width: 113px;
+    height: 113px;
+    margin: 0 0 9px 9px;
+    *margin: 0 0 6px 6px;
+    background-color: #eee;
+    overflow: hidden;
+    cursor: pointer;
+    position: relative;
+}
+#online li.clearFloat {
+    float: none;
+    clear: both;
+    display: block;
+    width:0;
+    height:0;
+    margin: 0;
+    padding: 0;
+}
+#online li img {
+    cursor: pointer;
+}
+#online li div.file-wrapper {
+    cursor: pointer;
+    position: absolute;
+    display: block;
+    width: 111px;
+    height: 111px;
+    border: 1px solid #eee;
+    background: url("images/bg.png") repeat;
+}
+#online li div span.file-title{
+    display: block;
+    padding: 0 3px;
+    margin: 3px 0 0 0;
+    font-size: 12px;
+    height: 13px;
+    color: #555555;
+    text-align: center;
+    width: 107px;
+    white-space: nowrap;
+    word-break: break-all;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+#online li .icon {
+    cursor: pointer;
+    width: 113px;
+    height: 113px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 2;
+    border: 0;
+    background-repeat: no-repeat;
+}
+#online li .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+}
+#online li.selected .icon {
+    background-image: url(images/success.png);
+    background-image: url(images/success.gif) \9;
+    background-position: 75px 75px;
+}
+#online li.selected .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+    background-position: 72px 72px;
+}
+
+
+/* 在线文件的文件预览图标 */
+i.file-preview {
+    display: block;
+    margin: 10px auto;
+    width: 70px;
+    height: 70px;
+    background-image: url("images/file-icons.png");
+    background-image: url("images/file-icons.gif") \9;
+    background-position: -140px center;
+    background-repeat: no-repeat;
+}
+i.file-preview.file-type-dir{
+    background-position: 0 center;
+}
+i.file-preview.file-type-file{
+    background-position: -140px center;
+}
+i.file-preview.file-type-filelist{
+    background-position: -210px center;
+}
+i.file-preview.file-type-zip,
+i.file-preview.file-type-rar,
+i.file-preview.file-type-7z,
+i.file-preview.file-type-tar,
+i.file-preview.file-type-gz,
+i.file-preview.file-type-bz2{
+    background-position: -280px center;
+}
+i.file-preview.file-type-xls,
+i.file-preview.file-type-xlsx{
+    background-position: -350px center;
+}
+i.file-preview.file-type-doc,
+i.file-preview.file-type-docx{
+    background-position: -420px center;
+}
+i.file-preview.file-type-ppt,
+i.file-preview.file-type-pptx{
+    background-position: -490px center;
+}
+i.file-preview.file-type-vsd{
+    background-position: -560px center;
+}
+i.file-preview.file-type-pdf{
+    background-position: -630px center;
+}
+i.file-preview.file-type-txt,
+i.file-preview.file-type-md,
+i.file-preview.file-type-json,
+i.file-preview.file-type-htm,
+i.file-preview.file-type-xml,
+i.file-preview.file-type-html,
+i.file-preview.file-type-js,
+i.file-preview.file-type-css,
+i.file-preview.file-type-php,
+i.file-preview.file-type-jsp,
+i.file-preview.file-type-asp{
+    background-position: -700px center;
+}
+i.file-preview.file-type-apk{
+    background-position: -770px center;
+}
+i.file-preview.file-type-exe{
+    background-position: -840px center;
+}
+i.file-preview.file-type-ipa{
+    background-position: -910px center;
+}
+i.file-preview.file-type-mp4,
+i.file-preview.file-type-swf,
+i.file-preview.file-type-mkv,
+i.file-preview.file-type-avi,
+i.file-preview.file-type-flv,
+i.file-preview.file-type-mov,
+i.file-preview.file-type-mpg,
+i.file-preview.file-type-mpeg,
+i.file-preview.file-type-ogv,
+i.file-preview.file-type-webm,
+i.file-preview.file-type-rm,
+i.file-preview.file-type-rmvb{
+    background-position: -980px center;
+}
+i.file-preview.file-type-ogg,
+i.file-preview.file-type-wav,
+i.file-preview.file-type-wmv,
+i.file-preview.file-type-mid,
+i.file-preview.file-type-mp3{
+    background-position: -1050px center;
+}
+i.file-preview.file-type-jpg,
+i.file-preview.file-type-jpeg,
+i.file-preview.file-type-gif,
+i.file-preview.file-type-bmp,
+i.file-preview.file-type-png,
+i.file-preview.file-type-psd{
+    background-position: -140px center;
+}

+ 60 - 0
public/Ueditor/dialogs/attachment/attachment.html

@@ -0,0 +1,60 @@
+<!doctype html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>ueditor图片对话框</title>
+    <script type="text/javascript" src="../internal.js"></script>
+
+    <!-- jquery -->
+    <script type="text/javascript" src="../../third-party/jquery-1.10.2.min.js"></script>
+
+    <!-- webuploader -->
+    <script src="../../third-party/webuploader/webuploader.min.js"></script>
+    <link rel="stylesheet" type="text/css" href="../../third-party/webuploader/webuploader.css">
+
+    <!-- attachment dialog -->
+    <link rel="stylesheet" href="attachment.css" type="text/css" />
+</head>
+<body>
+
+    <div class="wrapper">
+        <div id="tabhead" class="tabhead">
+            <span class="tab focus" data-content-id="upload"><var id="lang_tab_upload"></var></span>
+            <span class="tab" data-content-id="online"><var id="lang_tab_online"></var></span>
+        </div>
+        <div id="tabbody" class="tabbody">
+            <!-- 上传图片 -->
+            <div id="upload" class="panel focus">
+                <div id="queueList" class="queueList">
+                    <div class="statusBar element-invisible">
+                        <div class="progress">
+                            <span class="text">0%</span>
+                            <span class="percentage"></span>
+                        </div><div class="info"></div>
+                        <div class="btns">
+                            <div id="filePickerBtn"></div>
+                            <div class="uploadBtn"><var id="lang_start_upload"></var></div>
+                        </div>
+                    </div>
+                    <div id="dndArea" class="placeholder">
+                        <div class="filePickerContainer">
+                            <div id="filePickerReady"></div>
+                        </div>
+                    </div>
+                    <ul class="filelist element-invisible">
+                        <li id="filePickerBlock" class="filePickerBlock"></li>
+                    </ul>
+                </div>
+            </div>
+
+            <!-- 在线图片 -->
+            <div id="online" class="panel">
+                <div id="fileList"><var id="lang_imgLoading"></var></div>
+            </div>
+
+        </div>
+    </div>
+    <script type="text/javascript" src="attachment.js"></script>
+
+</body>
+</html>

+ 754 - 0
public/Ueditor/dialogs/attachment/attachment.js

@@ -0,0 +1,754 @@
+/**
+ * User: Jinqn
+ * Date: 14-04-08
+ * Time: 下午16:34
+ * 上传图片对话框逻辑代码,包括tab: 远程图片/上传图片/在线图片/搜索图片
+ */
+
+(function () {
+
+    var uploadFile,
+        onlineFile;
+
+    window.onload = function () {
+        initTabs();
+        initButtons();
+    };
+
+    /* 初始化tab标签 */
+    function initTabs() {
+        var tabs = $G('tabhead').children;
+        for (var i = 0; i < tabs.length; i++) {
+            domUtils.on(tabs[i], "click", function (e) {
+                var target = e.target || e.srcElement;
+                setTabFocus(target.getAttribute('data-content-id'));
+            });
+        }
+
+        setTabFocus('upload');
+    }
+
+    /* 初始化tabbody */
+    function setTabFocus(id) {
+        if(!id) return;
+        var i, bodyId, tabs = $G('tabhead').children;
+        for (i = 0; i < tabs.length; i++) {
+            bodyId = tabs[i].getAttribute('data-content-id')
+            if (bodyId == id) {
+                domUtils.addClass(tabs[i], 'focus');
+                domUtils.addClass($G(bodyId), 'focus');
+            } else {
+                domUtils.removeClasses(tabs[i], 'focus');
+                domUtils.removeClasses($G(bodyId), 'focus');
+            }
+        }
+        switch (id) {
+            case 'upload':
+                uploadFile = uploadFile || new UploadFile('queueList');
+                break;
+            case 'online':
+                onlineFile = onlineFile || new OnlineFile('fileList');
+                break;
+        }
+    }
+
+    /* 初始化onok事件 */
+    function initButtons() {
+
+        dialog.onok = function () {
+            var list = [], id, tabs = $G('tabhead').children;
+            for (var i = 0; i < tabs.length; i++) {
+                if (domUtils.hasClass(tabs[i], 'focus')) {
+                    id = tabs[i].getAttribute('data-content-id');
+                    break;
+                }
+            }
+
+            switch (id) {
+                case 'upload':
+                    list = uploadFile.getInsertList();
+                    var count = uploadFile.getQueueCount();
+                    if (count) {
+                        $('.info', '#queueList').html('<span style="color:red;">' + '还有2个未上传文件'.replace(/[\d]/, count) + '</span>');
+                        return false;
+                    }
+                    break;
+                case 'online':
+                    list = onlineFile.getInsertList();
+                    break;
+            }
+
+            editor.execCommand('insertfile', list);
+        };
+    }
+
+
+    /* 上传附件 */
+    function UploadFile(target) {
+        this.$wrap = target.constructor == String ? $('#' + target) : $(target);
+        this.init();
+    }
+    UploadFile.prototype = {
+        init: function () {
+            this.fileList = [];
+            this.initContainer();
+            this.initUploader();
+        },
+        initContainer: function () {
+            this.$queue = this.$wrap.find('.filelist');
+        },
+        /* 初始化容器 */
+        initUploader: function () {
+            var _this = this,
+                $ = jQuery,    // just in case. Make sure it's not an other libaray.
+                $wrap = _this.$wrap,
+            // 图片容器
+                $queue = $wrap.find('.filelist'),
+            // 状态栏,包括进度和控制按钮
+                $statusBar = $wrap.find('.statusBar'),
+            // 文件总体选择信息。
+                $info = $statusBar.find('.info'),
+            // 上传按钮
+                $upload = $wrap.find('.uploadBtn'),
+            // 上传按钮
+                $filePickerBtn = $wrap.find('.filePickerBtn'),
+            // 上传按钮
+                $filePickerBlock = $wrap.find('.filePickerBlock'),
+            // 没选择文件之前的内容。
+                $placeHolder = $wrap.find('.placeholder'),
+            // 总体进度条
+                $progress = $statusBar.find('.progress').hide(),
+            // 添加的文件数量
+                fileCount = 0,
+            // 添加的文件总大小
+                fileSize = 0,
+            // 优化retina, 在retina下这个值是2
+                ratio = window.devicePixelRatio || 1,
+            // 缩略图大小
+                thumbnailWidth = 113 * ratio,
+                thumbnailHeight = 113 * ratio,
+            // 可能有pedding, ready, uploading, confirm, done.
+                state = '',
+            // 所有文件的进度信息,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,
+                actionUrl = editor.getActionUrl(editor.getOpt('fileActionName')),
+                fileMaxSize = editor.getOpt('fileMaxSize'),
+                acceptExtensions = (editor.getOpt('fileAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');;
+
+            if (!WebUploader.Uploader.support()) {
+                $('#filePickerReady').after($('<div>').html(lang.errorNotSupport)).hide();
+                return;
+            } else if (!editor.getOpt('fileActionName')) {
+                $('#filePickerReady').after($('<div>').html(lang.errorLoadConfig)).hide();
+                return;
+            }
+
+            uploader = _this.uploader = WebUploader.create({
+                pick: {
+                    id: '#filePickerReady',
+                    label: lang.uploadSelectFile
+                },
+                swf: '../../third-party/webuploader/Uploader.swf',
+                server: actionUrl,
+                fileVal: editor.getOpt('fileFieldName'),
+                duplicate: true,
+                fileSingleSizeLimit: fileMaxSize,
+                compress: false
+            });
+            uploader.addButton({
+                id: '#filePickerBlock'
+            });
+            uploader.addButton({
+                id: '#filePickerBtn',
+                label: lang.uploadAddFile
+            });
+
+            setState('pedding');
+
+            // 当有文件添加进来时执行,负责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">' + lang.uploadDelete + '</span>' +
+                        '<span class="rotateRight">' + lang.uploadTurnRight + '</span>' +
+                        '<span class="rotateLeft">' + lang.uploadTurnLeft + '</span></div>').appendTo($li),
+                    $prgress = $li.find('p.progress span'),
+                    $wrap = $li.find('p.imgWrap'),
+                    $info = $('<p class="error"></p>').hide().appendTo($li),
+
+                    showError = function (code) {
+                        switch (code) {
+                            case 'exceed_size':
+                                text = lang.errorExceedSize;
+                                break;
+                            case 'interrupt':
+                                text = lang.errorInterrupt;
+                                break;
+                            case 'http':
+                                text = lang.errorHttp;
+                                break;
+                            case 'not_allow_type':
+                                text = lang.errorFileType;
+                                break;
+                            default:
+                                text = lang.errorUploadRetry;
+                                break;
+                        }
+                        $info.text(text).show();
+                    };
+
+                if (file.getStatus() === 'invalid') {
+                    showError(file.statusText);
+                } else {
+                    $wrap.text(lang.uploadPreview);
+                    if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) {
+                        $wrap.empty().addClass('notimage').append('<i class="file-preview file-type-' + file.ext.toLowerCase() + '"></i>' +
+                        '<span class="file-title" title="' + file.name + '">' + file.name + '</span>');
+                    } else {
+                        if (browser.ie && browser.version <= 7) {
+                            $wrap.text(lang.uploadNoPreview);
+                        } else {
+                            uploader.makeThumb(file, function (error, src) {
+                                if (error || !src) {
+                                    $wrap.text(lang.uploadNoPreview);
+                                } else {
+                                    var $img = $('<img src="' + src + '">');
+                                    $wrap.empty().append($img);
+                                    $img.on('error', function () {
+                                        $wrap.text(lang.uploadNoPreview);
+                                    });
+                                }
+                            }, thumbnailWidth, thumbnailHeight);
+                        }
+                    }
+                    percentages[ file.id ] = [ file.size, 0 ];
+                    file.rotation = 0;
+
+                    /* 检查文件格式 */
+                    if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) {
+                        showError('not_allow_type');
+                        uploader.removeFile(file);
+                    }
+                }
+
+                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') {
+                        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.hide();
+                        $prgress.css('display', 'block');
+                    } else if (cur === 'complete') {
+                    }
+
+                    $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) + ')');
+                    }
+
+                });
+
+                $li.insertBefore($filePickerBlock);
+            }
+
+            // 负责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 setState(val, files) {
+
+                if (val != state) {
+
+                    var stats = uploader.getStats();
+
+                    $upload.removeClass('state-' + state);
+                    $upload.addClass('state-' + val);
+
+                    switch (val) {
+
+                        /* 未选择文件 */
+                        case 'pedding':
+                            $queue.addClass('element-invisible');
+                            $statusBar.addClass('element-invisible');
+                            $placeHolder.removeClass('element-invisible');
+                            $progress.hide(); $info.hide();
+                            uploader.refresh();
+                            break;
+
+                        /* 可以开始上传 */
+                        case 'ready':
+                            $placeHolder.addClass('element-invisible');
+                            $queue.removeClass('element-invisible');
+                            $statusBar.removeClass('element-invisible');
+                            $progress.hide(); $info.show();
+                            $upload.text(lang.uploadStart);
+                            uploader.refresh();
+                            break;
+
+                        /* 上传中 */
+                        case 'uploading':
+                            $progress.show(); $info.hide();
+                            $upload.text(lang.uploadPause);
+                            break;
+
+                        /* 暂停上传 */
+                        case 'paused':
+                            $progress.show(); $info.hide();
+                            $upload.text(lang.uploadContinue);
+                            break;
+
+                        case 'confirm':
+                            $progress.show(); $info.hide();
+                            $upload.text(lang.uploadStart);
+
+                            stats = uploader.getStats();
+                            if (stats.successNum && !stats.uploadFailNum) {
+                                setState('finish');
+                                return;
+                            }
+                            break;
+
+                        case 'finish':
+                            $progress.hide(); $info.show();
+                            if (stats.uploadFailNum) {
+                                $upload.text(lang.uploadRetry);
+                            } else {
+                                $upload.text(lang.uploadStart);
+                            }
+                            break;
+                    }
+
+                    state = val;
+                    updateStatus();
+
+                }
+
+                if (!_this.getQueueCount()) {
+                    $upload.addClass('disabled')
+                } else {
+                    $upload.removeClass('disabled')
+                }
+
+            }
+
+            function updateStatus() {
+                var text = '', stats;
+
+                if (state === 'ready') {
+                    text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize));
+                } else if (state === 'confirm') {
+                    stats = uploader.getStats();
+                    if (stats.uploadFailNum) {
+                        text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum);
+                    }
+                } else {
+                    stats = uploader.getStats();
+                    text = lang.updateStatusFinish.replace('_', fileCount).
+                        replace('_KB', WebUploader.formatSize(fileSize)).
+                        replace('_', stats.successNum);
+
+                    if (stats.uploadFailNum) {
+                        text += lang.updateStatusError.replace('_', stats.uploadFailNum);
+                    }
+                }
+
+                $info.html(text);
+            }
+
+            uploader.on('fileQueued', function (file) {
+                fileCount++;
+                fileSize += file.size;
+
+                if (fileCount === 1) {
+                    $placeHolder.addClass('element-invisible');
+                    $statusBar.show();
+                }
+
+                addFile(file);
+            });
+
+            uploader.on('fileDequeued', function (file) {
+                fileCount--;
+                fileSize -= file.size;
+
+                removeFile(file);
+                updateTotalProgress();
+            });
+
+            uploader.on('filesQueued', function (file) {
+                if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) {
+                    setState('ready');
+                }
+                updateTotalProgress();
+            });
+
+            uploader.on('all', function (type, files) {
+                switch (type) {
+                    case 'uploadFinished':
+                        setState('confirm', files);
+                        break;
+                    case 'startUpload':
+                        /* 添加额外的GET参数 */
+                        var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '',
+                            url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params);
+                        uploader.option('server', url);
+                        setState('uploading', files);
+                        break;
+                    case 'stopUpload':
+                        setState('paused', files);
+                        break;
+                }
+            });
+
+            uploader.on('uploadBeforeSend', function (file, data, header) {
+                //这里可以通过data对象添加POST参数
+                header['X_Requested_With'] = 'XMLHttpRequest';
+            });
+
+            uploader.on('uploadProgress', function (file, percentage) {
+                var $li = $('#' + file.id),
+                    $percent = $li.find('.progress span');
+
+                $percent.css('width', percentage * 100 + '%');
+                percentages[ file.id ][ 1 ] = percentage;
+                updateTotalProgress();
+            });
+
+            uploader.on('uploadSuccess', function (file, ret) {
+                var $file = $('#' + file.id);
+                try {
+                    var responseText = (ret._raw || ret),
+                        json = utils.str2json(responseText);
+                    if (json.state == 'SUCCESS') {
+                        _this.fileList.push(json);
+                        $file.append('<span class="success"></span>');
+                    } else {
+                        $file.find('.error').text(json.state).show();
+                    }
+                } catch (e) {
+                    $file.find('.error').text(lang.errorServerUpload).show();
+                }
+            });
+
+            uploader.on('uploadError', function (file, code) {
+            });
+            uploader.on('error', function (code, file) {
+                if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') {
+                    addFile(file);
+                }
+            });
+            uploader.on('uploadComplete', function (file, ret) {
+            });
+
+            $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();
+                }
+            });
+
+            $upload.addClass('state-' + state);
+            updateTotalProgress();
+        },
+        getQueueCount: function () {
+            var file, i, status, readyFile = 0, files = this.uploader.getFiles();
+            for (i = 0; file = files[i++]; ) {
+                status = file.getStatus();
+                if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++;
+            }
+            return readyFile;
+        },
+        getInsertList: function () {
+            var i, link, data, list = [],
+                prefix = editor.getOpt('fileUrlPrefix');
+            for (i = 0; i < this.fileList.length; i++) {
+                data = this.fileList[i];
+                link = data.url;
+                list.push({
+                    title: data.original || link.substr(link.lastIndexOf('/') + 1),
+                    url: prefix + link
+                });
+            }
+            return list;
+        }
+    };
+
+
+    /* 在线附件 */
+    function OnlineFile(target) {
+        this.container = utils.isString(target) ? document.getElementById(target) : target;
+        this.init();
+    }
+    OnlineFile.prototype = {
+        init: function () {
+            this.initContainer();
+            this.initEvents();
+            this.initData();
+        },
+        /* 初始化容器 */
+        initContainer: function () {
+            this.container.innerHTML = '';
+            this.list = document.createElement('ul');
+            this.clearFloat = document.createElement('li');
+
+            domUtils.addClass(this.list, 'list');
+            domUtils.addClass(this.clearFloat, 'clearFloat');
+
+            this.list.appendChild(this.clearFloat);
+            this.container.appendChild(this.list);
+        },
+        /* 初始化滚动事件,滚动到地步自动拉取数据 */
+        initEvents: function () {
+            var _this = this;
+
+            /* 滚动拉取图片 */
+            domUtils.on($G('fileList'), 'scroll', function(e){
+                var panel = this;
+                if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) {
+                    _this.getFileData();
+                }
+            });
+            /* 选中图片 */
+            domUtils.on(this.list, 'click', function (e) {
+                var target = e.target || e.srcElement,
+                    li = target.parentNode;
+
+                if (li.tagName.toLowerCase() == 'li') {
+                    if (domUtils.hasClass(li, 'selected')) {
+                        domUtils.removeClasses(li, 'selected');
+                    } else {
+                        domUtils.addClass(li, 'selected');
+                    }
+                }
+            });
+        },
+        /* 初始化第一次的数据 */
+        initData: function () {
+
+            /* 拉取数据需要使用的值 */
+            this.state = 0;
+            this.listSize = editor.getOpt('fileManagerListSize');
+            this.listIndex = 0;
+            this.listEnd = false;
+
+            /* 第一次拉取数据 */
+            this.getFileData();
+        },
+        /* 向后台拉取图片列表数据 */
+        getFileData: function () {
+            var _this = this;
+
+            if(!_this.listEnd && !this.isLoadingData) {
+                this.isLoadingData = true;
+                ajax.request(editor.getActionUrl(editor.getOpt('fileManagerActionName')), {
+                    timeout: 100000,
+                    data: utils.extend({
+                            start: this.listIndex,
+                            size: this.listSize
+                        }, editor.queryCommandValue('serverparam')),
+                    method: 'get',
+                    onsuccess: function (r) {
+                        try {
+                            var json = eval('(' + r.responseText + ')');
+                            if (json.state == 'SUCCESS') {
+                                _this.pushData(json.list);
+                                _this.listIndex = parseInt(json.start) + parseInt(json.list.length);
+                                if(_this.listIndex >= json.total) {
+                                    _this.listEnd = true;
+                                }
+                                _this.isLoadingData = false;
+                            }
+                        } catch (e) {
+                            if(r.responseText.indexOf('ue_separate_ue') != -1) {
+                                var list = r.responseText.split(r.responseText);
+                                _this.pushData(list);
+                                _this.listIndex = parseInt(list.length);
+                                _this.listEnd = true;
+                                _this.isLoadingData = false;
+                            }
+                        }
+                    },
+                    onerror: function () {
+                        _this.isLoadingData = false;
+                    }
+                });
+            }
+        },
+        /* 添加图片到列表界面上 */
+        pushData: function (list) {
+            var i, item, img, filetype, preview, icon, _this = this,
+                urlPrefix = editor.getOpt('fileManagerUrlPrefix');
+            for (i = 0; i < list.length; i++) {
+                if(list[i] && list[i].url) {
+                    item = document.createElement('li');
+                    icon = document.createElement('span');
+                    filetype = list[i].url.substr(list[i].url.lastIndexOf('.') + 1);
+
+                    if ( "png|jpg|jpeg|gif|bmp".indexOf(filetype) != -1 ) {
+                        preview = document.createElement('img');
+                        domUtils.on(preview, 'load', (function(image){
+                            return function(){
+                                _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight);
+                            };
+                        })(preview));
+                        preview.width = 113;
+                        preview.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) );
+                    } else {
+                        var ic = document.createElement('i'),
+                            textSpan = document.createElement('span');
+                        textSpan.innerHTML = list[i].url.substr(list[i].url.lastIndexOf('/') + 1);
+                        preview = document.createElement('div');
+                        preview.appendChild(ic);
+                        preview.appendChild(textSpan);
+                        domUtils.addClass(preview, 'file-wrapper');
+                        domUtils.addClass(textSpan, 'file-title');
+                        domUtils.addClass(ic, 'file-type-' + filetype);
+                        domUtils.addClass(ic, 'file-preview');
+                    }
+                    domUtils.addClass(icon, 'icon');
+                    item.setAttribute('data-url', urlPrefix + list[i].url);
+                    if (list[i].original) {
+                        item.setAttribute('data-title', list[i].original);
+                    }
+
+                    item.appendChild(preview);
+                    item.appendChild(icon);
+                    this.list.insertBefore(item, this.clearFloat);
+                }
+            }
+        },
+        /* 改变图片大小 */
+        scale: function (img, w, h, type) {
+            var ow = img.width,
+                oh = img.height;
+
+            if (type == 'justify') {
+                if (ow >= oh) {
+                    img.width = w;
+                    img.height = h * oh / ow;
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
+                } else {
+                    img.width = w * ow / oh;
+                    img.height = h;
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
+                }
+            } else {
+                if (ow >= oh) {
+                    img.width = w * ow / oh;
+                    img.height = h;
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
+                } else {
+                    img.width = w;
+                    img.height = h * oh / ow;
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
+                }
+            }
+        },
+        getInsertList: function () {
+            var i, lis = this.list.children, list = [];
+            for (i = 0; i < lis.length; i++) {
+                if (domUtils.hasClass(lis[i], 'selected')) {
+                    var url = lis[i].getAttribute('data-url');
+                    var title = lis[i].getAttribute('data-title') || url.substr(url.lastIndexOf('/') + 1);
+                    list.push({
+                        title: title,
+                        url: url
+                    });
+                }
+            }
+            return list;
+        }
+    };
+
+
+})();

BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_chm.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_default.png


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_doc.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_exe.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_jpg.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_mp3.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_mv.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_pdf.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_ppt.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_psd.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_rar.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_txt.gif


BIN
public/Ueditor/dialogs/attachment/fileTypeImages/icon_xls.gif


BIN
public/Ueditor/dialogs/attachment/images/alignicon.gif


BIN
public/Ueditor/dialogs/attachment/images/alignicon.png


BIN
public/Ueditor/dialogs/attachment/images/bg.png


BIN
public/Ueditor/dialogs/attachment/images/file-icons.gif


BIN
public/Ueditor/dialogs/attachment/images/file-icons.png


BIN
public/Ueditor/dialogs/attachment/images/icons.gif


BIN
public/Ueditor/dialogs/attachment/images/icons.png


BIN
public/Ueditor/dialogs/attachment/images/image.png


BIN
public/Ueditor/dialogs/attachment/images/progress.png


BIN
public/Ueditor/dialogs/attachment/images/success.gif


BIN
public/Ueditor/dialogs/attachment/images/success.png


+ 94 - 0
public/Ueditor/dialogs/background/background.css

@@ -0,0 +1,94 @@
+.wrapper{ width: 424px;margin: 10px auto; zoom:1;position: relative}
+.tabbody{height:225px;}
+.tabbody .panel { position: absolute;width:100%; height:100%;background: #fff; display: none;}
+.tabbody .focus { display: block;}
+
+body{font-size: 12px;color: #888;overflow: hidden;}
+input,label{vertical-align:middle}
+.clear{clear: both;}
+.pl{padding-left: 18px;padding-left: 23px\9;}
+
+#imageList {width: 420px;height: 215px;margin-top: 10px;overflow: hidden;overflow-y: auto;}
+#imageList div {float: left;width: 100px;height: 95px;margin: 5px 10px;}
+#imageList img {cursor: pointer;border: 2px solid white;}
+
+.bgarea{margin: 10px;padding: 5px;height: 84%;border: 1px solid #A8A297;}
+.content div{margin: 10px 0 10px 5px;}
+.content .iptradio{margin: 0px 5px 5px 0px;}
+.txt{width:280px;}
+
+.wrapcolor{height: 19px;}
+div.color{float: left;margin: 0;}
+#colorPicker{width: 17px;height: 17px;border: 1px solid #CCC;display: inline-block;border-radius: 3px;box-shadow: 2px 2px 5px #D3D6DA;margin: 0;float: left;}
+div.alignment,#custom{margin-left: 23px;margin-left: 28px\9;}
+#custom input{height: 15px;min-height: 15px;width:20px;}
+#repeatType{width:100px;}
+
+
+/* 图片管理样式 */
+#imgManager {
+    width: 100%;
+    height: 225px;
+}
+#imgManager #imageList{
+    width: 100%;
+    overflow-x: hidden;
+    overflow-y: auto;
+}
+#imgManager ul {
+    display: block;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+#imgManager li {
+    float: left;
+    display: block;
+    list-style: none;
+    padding: 0;
+    width: 113px;
+    height: 113px;
+    margin: 9px 0 0 19px;
+    background-color: #eee;
+    overflow: hidden;
+    cursor: pointer;
+    position: relative;
+}
+#imgManager li.clearFloat {
+    float: none;
+    clear: both;
+    display: block;
+    width:0;
+    height:0;
+    margin: 0;
+    padding: 0;
+}
+#imgManager li img {
+    cursor: pointer;
+}
+#imgManager li .icon {
+    cursor: pointer;
+    width: 113px;
+    height: 113px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 2;
+    border: 0;
+    background-repeat: no-repeat;
+}
+#imgManager li .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+}
+#imgManager li.selected .icon {
+    background-image: url(images/success.png);
+    background-position: 75px 75px;
+}
+#imgManager li.selected .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+    background-position: 72px 72px;
+}

+ 56 - 0
public/Ueditor/dialogs/background/background.html

@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
+    <script type="text/javascript" src="../internal.js"></script>
+    <link rel="stylesheet" type="text/css" href="background.css">
+</head>
+<body>
+    <div id="bg_container" class="wrapper">
+        <div id="tabHeads" class="tabhead">
+            <span class="focus" data-content-id="normal"><var id="lang_background_normal"></var></span>
+            <span class="" data-content-id="imgManager"><var id="lang_background_local"></var></span>
+        </div>
+        <div id="tabBodys" class="tabbody">
+            <div id="normal" class="panel focus">
+                <fieldset class="bgarea">
+                    <legend><var id="lang_background_set"></var></legend>
+                    <div class="content">
+                        <div>
+                            <label><input id="nocolorRadio" class="iptradio" type="radio" name="t" value="none" checked="checked"><var id="lang_background_none"></var></label>
+                            <label><input id="coloredRadio" class="iptradio" type="radio" name="t" value="color"><var id="lang_background_colored"></var></label>
+                        </div>
+                        <div class="wrapcolor pl">
+                            <div class="color">
+                                <var id="lang_background_color"></var>:
+                            </div>
+                            <div id="colorPicker"></div>
+                            <div class="clear"></div>
+                        </div>
+                        <div class="wrapcolor pl">
+                            <label><var id="lang_background_netimg"></var>:</label><input class="txt" type="text" id="url">
+                        </div>
+                        <div id="alignment" class="alignment">
+                            <var id="lang_background_align"></var>:<select id="repeatType">
+                                <option value="center"></option>
+                                <option value="repeat-x"></option>
+                                <option value="repeat-y"></option>
+                                <option value="repeat"></option>
+                                <option value="self"></option>
+                            </select>
+                        </div>
+                        <div id="custom" >
+                            <var id="lang_background_position"></var>:x:<input type="text" size="1" id="x" maxlength="4" value="0">px&nbsp;&nbsp;y:<input type="text" size="1" id="y" maxlength="4" value="0">px
+                        </div>
+                    </div>
+                </fieldset>
+
+            </div>
+            <div id="imgManager" class="panel">
+                <div id="imageList" style=""></div>
+            </div>
+        </div>
+    </div>
+    <script type="text/javascript" src="background.js"></script>
+</body>
+</html>

+ 376 - 0
public/Ueditor/dialogs/background/background.js

@@ -0,0 +1,376 @@
+(function () {
+
+    var onlineImage,
+        backupStyle = editor.queryCommandValue('background');
+
+    window.onload = function () {
+        initTabs();
+        initColorSelector();
+    };
+
+    /* 初始化tab标签 */
+    function initTabs(){
+        var tabs = $G('tabHeads').children;
+        for (var i = 0; i < tabs.length; i++) {
+            domUtils.on(tabs[i], "click", function (e) {
+                var target = e.target || e.srcElement;
+                for (var j = 0; j < tabs.length; j++) {
+                    if(tabs[j] == target){
+                        tabs[j].className = "focus";
+                        var contentId = tabs[j].getAttribute('data-content-id');
+                        $G(contentId).style.display = "block";
+                        if(contentId == 'imgManager') {
+                            initImagePanel();
+                        }
+                    }else {
+                        tabs[j].className = "";
+                        $G(tabs[j].getAttribute('data-content-id')).style.display = "none";
+                    }
+                }
+            });
+        }
+    }
+
+    /* 初始化颜色设置 */
+    function initColorSelector () {
+        var obj = editor.queryCommandValue('background');
+        if (obj) {
+            var color = obj['background-color'],
+                repeat = obj['background-repeat'] || 'repeat',
+                image = obj['background-image'] || '',
+                position = obj['background-position'] || 'center center',
+                pos = position.split(' '),
+                x = parseInt(pos[0]) || 0,
+                y = parseInt(pos[1]) || 0;
+
+            if(repeat == 'no-repeat' && (x || y)) repeat = 'self';
+
+            image = image.match(/url[\s]*\(([^\)]*)\)/);
+            image = image ? image[1]:'';
+            updateFormState('colored', color, image, repeat, x, y);
+        } else {
+            updateFormState();
+        }
+
+        var updateHandler = function () {
+            updateFormState();
+            updateBackground();
+        }
+        domUtils.on($G('nocolorRadio'), 'click', updateBackground);
+        domUtils.on($G('coloredRadio'), 'click', updateHandler);
+        domUtils.on($G('url'), 'keyup', function(){
+            if($G('url').value && $G('alignment').style.display == "none") {
+                utils.each($G('repeatType').children, function(item){
+                    item.selected = ('repeat' == item.getAttribute('value') ? 'selected':false);
+                });
+            }
+            updateHandler();
+        });
+        domUtils.on($G('repeatType'), 'change', updateHandler);
+        domUtils.on($G('x'), 'keyup', updateBackground);
+        domUtils.on($G('y'), 'keyup', updateBackground);
+
+        initColorPicker();
+    }
+
+    /* 初始化颜色选择器 */
+    function initColorPicker() {
+        var me = editor,
+            cp = $G("colorPicker");
+
+        /* 生成颜色选择器ui对象 */
+        var popup = new UE.ui.Popup({
+            content: new UE.ui.ColorPicker({
+                noColorText: me.getLang("clearColor"),
+                editor: me,
+                onpickcolor: function (t, color) {
+                    updateFormState('colored', color);
+                    updateBackground();
+                    UE.ui.Popup.postHide();
+                },
+                onpicknocolor: function (t, color) {
+                    updateFormState('colored', 'transparent');
+                    updateBackground();
+                    UE.ui.Popup.postHide();
+                }
+            }),
+            editor: me,
+            onhide: function () {
+            }
+        });
+
+        /* 设置颜色选择器 */
+        domUtils.on(cp, "click", function () {
+            popup.showAnchor(this);
+        });
+        domUtils.on(document, 'mousedown', function (evt) {
+            var el = evt.target || evt.srcElement;
+            UE.ui.Popup.postHide(el);
+        });
+        domUtils.on(window, 'scroll', function () {
+            UE.ui.Popup.postHide();
+        });
+    }
+
+    /* 初始化在线图片列表 */
+    function initImagePanel() {
+        onlineImage = onlineImage || new OnlineImage('imageList');
+    }
+
+    /* 更新背景色设置面板 */
+    function updateFormState (radio, color, url, align, x, y) {
+        var nocolorRadio = $G('nocolorRadio'),
+            coloredRadio = $G('coloredRadio');
+
+        if(radio) {
+            nocolorRadio.checked = (radio == 'colored' ? false:'checked');
+            coloredRadio.checked = (radio == 'colored' ? 'checked':false);
+        }
+        if(color) {
+            domUtils.setStyle($G("colorPicker"), "background-color", color);
+        }
+
+        if(url && /^\//.test(url)) {
+            var a = document.createElement('a');
+            a.href = url;
+            browser.ie && (a.href = a.href);
+            url = browser.ie ? a.href:(a.protocol + '//' + a.host + a.pathname + a.search + a.hash);
+        }
+
+        if(url || url === '') {
+            $G('url').value = url;
+        }
+        if(align) {
+            utils.each($G('repeatType').children, function(item){
+                item.selected = (align == item.getAttribute('value') ? 'selected':false);
+            });
+        }
+        if(x || y) {
+            $G('x').value = parseInt(x) || 0;
+            $G('y').value = parseInt(y) || 0;
+        }
+
+        $G('alignment').style.display = coloredRadio.checked && $G('url').value ? '':'none';
+        $G('custom').style.display = coloredRadio.checked && $G('url').value && $G('repeatType').value == 'self' ? '':'none';
+    }
+
+    /* 更新背景颜色 */
+    function updateBackground () {
+        if ($G('coloredRadio').checked) {
+            var color = domUtils.getStyle($G("colorPicker"), "background-color"),
+                bgimg = $G("url").value,
+                align = $G("repeatType").value,
+                backgroundObj = {
+                    "background-repeat": "no-repeat",
+                    "background-position": "center center"
+                };
+
+            if (color) backgroundObj["background-color"] = color;
+            if (bgimg) backgroundObj["background-image"] = 'url(' + bgimg + ')';
+            if (align == 'self') {
+                backgroundObj["background-position"] = $G("x").value + "px " + $G("y").value + "px";
+            } else if (align == 'repeat-x' || align == 'repeat-y' || align == 'repeat') {
+                backgroundObj["background-repeat"] = align;
+            }
+
+            editor.execCommand('background', backgroundObj);
+        } else {
+            editor.execCommand('background', null);
+        }
+    }
+
+
+    /* 在线图片 */
+    function OnlineImage(target) {
+        this.container = utils.isString(target) ? document.getElementById(target) : target;
+        this.init();
+    }
+    OnlineImage.prototype = {
+        init: function () {
+            this.reset();
+            this.initEvents();
+        },
+        /* 初始化容器 */
+        initContainer: function () {
+            this.container.innerHTML = '';
+            this.list = document.createElement('ul');
+            this.clearFloat = document.createElement('li');
+
+            domUtils.addClass(this.list, 'list');
+            domUtils.addClass(this.clearFloat, 'clearFloat');
+
+            this.list.id = 'imageListUl';
+            this.list.appendChild(this.clearFloat);
+            this.container.appendChild(this.list);
+        },
+        /* 初始化滚动事件,滚动到地步自动拉取数据 */
+        initEvents: function () {
+            var _this = this;
+
+            /* 滚动拉取图片 */
+            domUtils.on($G('imageList'), 'scroll', function(e){
+                var panel = this;
+                if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) {
+                    _this.getImageData();
+                }
+            });
+            /* 选中图片 */
+            domUtils.on(this.container, 'click', function (e) {
+                var target = e.target || e.srcElement,
+                    li = target.parentNode,
+                    nodes = $G('imageListUl').childNodes;
+
+                if (li.tagName.toLowerCase() == 'li') {
+                    updateFormState('nocolor', null, '');
+                    for (var i = 0, node; node = nodes[i++];) {
+                        if (node == li && !domUtils.hasClass(node, 'selected')) {
+                            domUtils.addClass(node, 'selected');
+                            updateFormState('colored', null, li.firstChild.getAttribute("_src"), 'repeat');
+                        } else {
+                            domUtils.removeClasses(node, 'selected');
+                        }
+                    }
+                    updateBackground();
+                }
+            });
+        },
+        /* 初始化第一次的数据 */
+        initData: function () {
+
+            /* 拉取数据需要使用的值 */
+            this.state = 0;
+            this.listSize = editor.getOpt('imageManagerListSize');
+            this.listIndex = 0;
+            this.listEnd = false;
+
+            /* 第一次拉取数据 */
+            this.getImageData();
+        },
+        /* 重置界面 */
+        reset: function() {
+            this.initContainer();
+            this.initData();
+        },
+        /* 向后台拉取图片列表数据 */
+        getImageData: function () {
+            var _this = this;
+
+            if(!_this.listEnd && !this.isLoadingData) {
+                this.isLoadingData = true;
+                var url = editor.getActionUrl(editor.getOpt('imageManagerActionName')),
+                    isJsonp = utils.isCrossDomainUrl(url);
+                ajax.request(url, {
+                    'timeout': 100000,
+                    'dataType': isJsonp ? 'jsonp':'',
+                    'data': utils.extend({
+                            start: this.listIndex,
+                            size: this.listSize
+                        }, editor.queryCommandValue('serverparam')),
+                    'method': 'get',
+                    'onsuccess': function (r) {
+                        try {
+                            var json = isJsonp ? r:eval('(' + r.responseText + ')');
+                            if (json.state == 'SUCCESS') {
+                                _this.pushData(json.list);
+                                _this.listIndex = parseInt(json.start) + parseInt(json.list.length);
+                                if(_this.listIndex >= json.total) {
+                                    _this.listEnd = true;
+                                }
+                                _this.isLoadingData = false;
+                            }
+                        } catch (e) {
+                            if(r.responseText.indexOf('ue_separate_ue') != -1) {
+                                var list = r.responseText.split(r.responseText);
+                                _this.pushData(list);
+                                _this.listIndex = parseInt(list.length);
+                                _this.listEnd = true;
+                                _this.isLoadingData = false;
+                            }
+                        }
+                    },
+                    'onerror': function () {
+                        _this.isLoadingData = false;
+                    }
+                });
+            }
+        },
+        /* 添加图片到列表界面上 */
+        pushData: function (list) {
+            var i, item, img, icon, _this = this,
+                urlPrefix = editor.getOpt('imageManagerUrlPrefix');
+            for (i = 0; i < list.length; i++) {
+                if(list[i] && list[i].url) {
+                    item = document.createElement('li');
+                    img = document.createElement('img');
+                    icon = document.createElement('span');
+
+                    domUtils.on(img, 'load', (function(image){
+                        return function(){
+                            _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight);
+                        }
+                    })(img));
+                    img.width = 113;
+                    img.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) );
+                    img.setAttribute('_src', urlPrefix + list[i].url);
+                    domUtils.addClass(icon, 'icon');
+
+                    item.appendChild(img);
+                    item.appendChild(icon);
+                    this.list.insertBefore(item, this.clearFloat);
+                }
+            }
+        },
+        /* 改变图片大小 */
+        scale: function (img, w, h, type) {
+            var ow = img.width,
+                oh = img.height;
+
+            if (type == 'justify') {
+                if (ow >= oh) {
+                    img.width = w;
+                    img.height = h * oh / ow;
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
+                } else {
+                    img.width = w * ow / oh;
+                    img.height = h;
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
+                }
+            } else {
+                if (ow >= oh) {
+                    img.width = w * ow / oh;
+                    img.height = h;
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
+                } else {
+                    img.width = w;
+                    img.height = h * oh / ow;
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
+                }
+            }
+        },
+        getInsertList: function () {
+            var i, lis = this.list.children, list = [], align = getAlign();
+            for (i = 0; i < lis.length; i++) {
+                if (domUtils.hasClass(lis[i], 'selected')) {
+                    var img = lis[i].firstChild,
+                        src = img.getAttribute('_src');
+                    list.push({
+                        src: src,
+                        _src: src,
+                        floatStyle: align
+                    });
+                }
+
+            }
+            return list;
+        }
+    };
+
+    dialog.onok = function () {
+        updateBackground();
+        editor.fireEvent('saveScene');
+    };
+    dialog.oncancel = function () {
+        editor.execCommand('background', backupStyle);
+    };
+
+})();

BIN
public/Ueditor/dialogs/background/images/bg.png


BIN
public/Ueditor/dialogs/background/images/success.png


+ 65 - 0
public/Ueditor/dialogs/charts/chart.config.js

@@ -0,0 +1,65 @@
+/*
+ * 图表配置文件
+ * */
+
+
+//不同类型的配置
+var typeConfig = [
+    {
+        chart: {
+            type: 'line'
+        },
+        plotOptions: {
+            line: {
+                dataLabels: {
+                    enabled: false
+                },
+                enableMouseTracking: true
+            }
+        }
+    }, {
+        chart: {
+            type: 'line'
+        },
+        plotOptions: {
+            line: {
+                dataLabels: {
+                    enabled: true
+                },
+                enableMouseTracking: false
+            }
+        }
+    }, {
+        chart: {
+            type: 'area'
+        }
+    }, {
+        chart: {
+            type: 'bar'
+        }
+    }, {
+        chart: {
+            type: 'column'
+        }
+    }, {
+        chart: {
+            plotBackgroundColor: null,
+            plotBorderWidth: null,
+            plotShadow: false
+        },
+        plotOptions: {
+            pie: {
+                allowPointSelect: true,
+                cursor: 'pointer',
+                dataLabels: {
+                    enabled: true,
+                    color: '#000000',
+                    connectorColor: '#000000',
+                    formatter: function() {
+                        return '<b>'+ this.point.name +'</b>: '+ ( Math.round( this.point.percentage*100 ) / 100 ) +' %';
+                    }
+                }
+            }
+        }
+    }
+];

+ 165 - 0
public/Ueditor/dialogs/charts/charts.css

@@ -0,0 +1,165 @@
+html, body {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    overflow-x: hidden;
+}
+
+.main {
+    width: 100%;
+    overflow: hidden;
+}
+
+.table-view {
+    height: 100%;
+    float: left;
+    margin: 20px;
+    width: 40%;
+}
+
+.table-view .table-container {
+    width: 100%;
+    margin-bottom: 50px;
+    overflow: scroll;
+}
+
+.table-view th {
+    padding: 5px 10px;
+    background-color: #F7F7F7;
+}
+
+.table-view td {
+    width: 50px;
+    text-align: center;
+    padding:0;
+}
+
+.table-container input {
+    width: 40px;
+    padding: 5px;
+    border: none;
+    outline: none;
+}
+
+.table-view caption {
+    font-size: 18px;
+    text-align: left;
+}
+
+.charts-view {
+    /*margin-left: 49%!important;*/
+    width: 50%;
+    margin-left: 49%;
+    height: 400px;
+}
+
+.charts-container {
+    border-left: 1px solid #c3c3c3;
+}
+
+.charts-format fieldset {
+    padding-left: 20px;
+    margin-bottom: 50px;
+}
+
+.charts-format legend {
+    padding-left: 10px;
+    padding-right: 10px;
+}
+
+.format-item-container {
+    padding: 20px;
+}
+
+.format-item-container label {
+    display: block;
+    margin: 10px 0;
+}
+
+.charts-format .data-item {
+    border: 1px solid black;
+    outline: none;
+    padding: 2px 3px;
+}
+
+/* 图表类型 */
+
+.charts-type {
+    margin-top: 50px;
+    height: 300px;
+}
+
+.scroll-view {
+    border: 1px solid #c3c3c3;
+    border-left: none;
+    border-right: none;
+    overflow: hidden;
+}
+
+.scroll-container {
+    margin: 20px;
+    width: 100%;
+    overflow: hidden;
+}
+
+.scroll-bed {
+    width: 10000px;
+    _margin-top: 20px;
+    -webkit-transition: margin-left .5s ease;
+    -moz-transition: margin-left .5s ease;
+    transition: margin-left .5s ease;
+}
+
+.view-box {
+    display: inline-block;
+    *display: inline;
+    *zoom: 1;
+    margin-right: 20px;
+    border: 2px solid white;
+    line-height: 0;
+    overflow: hidden;
+    cursor: pointer;
+}
+
+.view-box img {
+    border: 1px solid #cecece;
+}
+
+.view-box.selected {
+    border-color: #7274A7;
+}
+
+.button-container {
+    margin-bottom: 20px;
+    text-align: center;
+}
+
+.button-container a {
+    display: inline-block;
+    width: 100px;
+    height: 25px;
+    line-height: 25px;
+    border: 1px solid #c2ccd1;
+    margin-right: 30px;
+    text-decoration: none;
+    color: black;
+    -webkit-border-radius: 2px;
+    -moz-border-radius: 2px;
+    border-radius: 2px;
+}
+
+.button-container a:HOVER {
+    background: #fcfcfc;
+}
+
+.button-container a:ACTIVE {
+    border-top-color: #c2ccd1;
+    box-shadow:inset 0 5px 4px -4px rgba(49, 49, 64, 0.1);
+}
+
+.edui-charts-not-data {
+    height: 100px;
+    line-height: 100px;
+    text-align: center;
+}

+ 89 - 0
public/Ueditor/dialogs/charts/charts.html

@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>chart</title>
+        <meta chartset="utf-8">
+        <link rel="stylesheet" type="text/css" href="charts.css">
+        <script type="text/javascript" src="../internal.js"></script>
+    </head>
+    <body>
+        <div class="main">
+            <div class="table-view">
+                <h3><var id="lang_data_source"></var></h3>
+                <div id="tableContainer" class="table-container"></div>
+                <h3><var id="lang_chart_format"></var></h3>
+                <form name="data-form">
+                    <div class="charts-format">
+                        <fieldset>
+                            <legend><var id="lang_data_align"></var></legend>
+                            <div class="format-item-container">
+                                <label>
+                                    <input type="radio" class="format-ctrl not-pie-item" name="charts-format" value="1" checked="checked">
+                                    <var id="lang_chart_align_same"></var>
+                                </label>
+                                <label>
+                                    <input type="radio" class="format-ctrl not-pie-item" name="charts-format" value="-1">
+                                    <var id="lang_chart_align_reverse"></var>
+                                </label>
+                                <br>
+                            </div>
+                        </fieldset>
+                        <fieldset>
+                            <legend><var id="lang_chart_title"></var></legend>
+                            <div class="format-item-container">
+                                <label>
+                                    <var id="lang_chart_main_title"></var><input type="text" name="title" class="data-item">
+                                </label>
+                                <label>
+                                    <var id="lang_chart_sub_title"></var><input type="text" name="sub-title" class="data-item not-pie-item">
+                                </label>
+                                <label>
+                                    <var id="lang_chart_x_title"></var><input type="text" name="x-title" class="data-item not-pie-item">
+                                </label>
+                                <label>
+                                    <var id="lang_chart_y_title"></var><input type="text" name="y-title" class="data-item not-pie-item">
+                                </label>
+                            </div>
+                        </fieldset>
+                        <fieldset>
+                            <legend><var id="lang_chart_tip"></var></legend>
+                            <div class="format-item-container">
+                                <label>
+                                    <var id="lang_cahrt_tip_prefix"></var>
+                                    <input type="text" id="tipInput" name="tip" class="data-item" disabled="disabled">
+                                </label>
+                                <p><var id="lang_cahrt_tip_description"></var></p>
+                            </div>
+                        </fieldset>
+                        <fieldset>
+                            <legend><var id="lang_chart_data_unit"></var></legend>
+                            <div class="format-item-container">
+                                <label><var id="lang_chart_data_unit_title"></var><input type="text" name="unit" class="data-item"></label>
+                                <p><var id="lang_chart_data_unit_description"></var></p>
+                            </div>
+                        </fieldset>
+                    </div>
+                </form>
+            </div>
+            <div class="charts-view">
+                <div id="chartsContainer" class="charts-container"></div>
+                <div id="chartsType" class="charts-type">
+                    <h3><var id="lang_chart_type"></var></h3>
+                    <div class="scroll-view">
+                        <div class="scroll-container">
+                            <div id="scrollBed" class="scroll-bed"></div>
+                        </div>
+                        <div id="buttonContainer" class="button-container">
+                            <a href="#" data-title="prev"><var id="lang_prev_btn"></var></a>
+                            <a href="#" data-title="next"><var id="lang_next_btn"></var></a>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+        <script src="../../third-party/jquery-1.10.2.min.js"></script>
+        <script src="../../third-party/highcharts/highcharts.js"></script>
+        <script src="chart.config.js"></script>
+        <script src="charts.js"></script>
+    </body>
+</html>

+ 519 - 0
public/Ueditor/dialogs/charts/charts.js

@@ -0,0 +1,519 @@
+/*
+ * 图片转换对话框脚本
+ **/
+
+var tableData = [],
+    //编辑器页面table
+    editorTable = null,
+    chartsConfig = window.typeConfig,
+    resizeTimer = null,
+    //初始默认图表类型
+    currentChartType = 0;
+
+window.onload = function () {
+
+    editorTable = domUtils.findParentByTagName(editor.selection.getRange().startContainer, 'table', true);
+
+    //未找到表格, 显示错误页面
+    if (!editorTable) {
+        document.body.innerHTML = "<div class='edui-charts-not-data'>未找到数据</div>";
+        return;
+    }
+
+    //初始化图表类型选择
+    initChartsTypeView();
+    renderTable(editorTable);
+    initEvent();
+    initUserConfig(editorTable.getAttribute("data-chart"));
+    $("#scrollBed .view-box:eq(" + currentChartType + ")").trigger("click");
+    updateViewType(currentChartType);
+
+    dialog.addListener("resize", function () {
+
+        if (resizeTimer != null) {
+            window.clearTimeout(resizeTimer);
+        }
+
+        resizeTimer = window.setTimeout(function () {
+
+            resizeTimer = null;
+
+            renderCharts();
+
+        }, 500);
+
+    });
+
+};
+
+function initChartsTypeView() {
+
+    var contents = [];
+
+    for (var i = 0, len = chartsConfig.length; i < len; i++) {
+
+        contents.push('<div class="view-box" data-chart-type="' + i + '"><img width="300" src="images/charts' + i + '.png"></div>');
+
+    }
+
+    $("#scrollBed").html(contents.join(""));
+
+}
+
+//渲染table, 以便用户修改数据
+function renderTable(table) {
+
+    var tableHtml = [];
+
+    //构造数据
+    for (var i = 0, row; row = table.rows[i]; i++) {
+
+        tableData[i] = [];
+        tableHtml[i] = [];
+
+        for (var j = 0, cell; cell = row.cells[j]; j++) {
+
+            var value = getCellValue(cell);
+
+            if (i > 0 && j > 0) {
+                value = +value;
+            }
+
+            if (i === 0 || j === 0) {
+                tableHtml[i].push('<th>' + value + '</th>');
+            } else {
+                tableHtml[i].push('<td><input type="text" class="data-item" value="' + value + '"></td>');
+            }
+
+            tableData[i][j] = value;
+
+        }
+
+        tableHtml[i] = tableHtml[i].join("");
+
+    }
+
+    //draw 表格
+    $("#tableContainer").html('<table id="showTable" border="1"><tbody><tr>' + tableHtml.join("</tr><tr>") + '</tr></tbody></table>');
+
+}
+
+/*
+ * 根据表格已有的图表属性初始化当前图表属性
+ */
+function initUserConfig(config) {
+
+    var parsedConfig = {};
+
+    if (!config) {
+        return;
+    }
+
+    config = config.split(";");
+
+    $.each(config, function (index, item) {
+
+        item = item.split(":");
+        parsedConfig[item[0]] = item[1];
+
+    });
+
+    setUserConfig(parsedConfig);
+
+}
+
+function initEvent() {
+
+    var cacheValue = null,
+        //图表类型数
+        typeViewCount = chartsConfig.length - 1,
+        $chartsTypeViewBox = $('#scrollBed .view-box');
+
+    $(".charts-format").delegate(".format-ctrl", "change", function () {
+
+        renderCharts();
+
+    })
+
+    $(".table-view").delegate(".data-item", "focus", function () {
+
+        cacheValue = this.value;
+
+    }).delegate(".data-item", "blur", function () {
+
+        if (this.value !== cacheValue) {
+            renderCharts();
+        }
+
+        cacheValue = null;
+
+    });
+
+    $("#buttonContainer").delegate("a", "click", function (e) {
+
+        e.preventDefault();
+
+        if (this.getAttribute("data-title") === 'prev') {
+
+            if (currentChartType > 0) {
+                currentChartType--;
+                updateViewType(currentChartType);
+            }
+
+        } else {
+
+            if (currentChartType < typeViewCount) {
+                currentChartType++;
+                updateViewType(currentChartType);
+            }
+
+        }
+
+    });
+
+    //图表类型变化
+    $('#scrollBed').delegate(".view-box", "click", function (e) {
+
+        var index = $(this).attr("data-chart-type");
+        $chartsTypeViewBox.removeClass("selected");
+        $($chartsTypeViewBox[index]).addClass("selected");
+
+        currentChartType = index | 0;
+
+        //饼图, 禁用部分配置
+        if (currentChartType === chartsConfig.length - 1) {
+
+            disableNotPieConfig();
+
+            //启用完整配置
+        } else {
+
+            enableNotPieConfig();
+
+        }
+
+        renderCharts();
+
+    });
+
+}
+
+function renderCharts() {
+
+    var data = collectData();
+
+    $('#chartsContainer').highcharts($.extend({}, chartsConfig[currentChartType], {
+
+        credits: {
+            enabled: false
+        },
+        exporting: {
+            enabled: false
+        },
+        title: {
+            text: data.title,
+            x: -20 //center
+        },
+        subtitle: {
+            text: data.subTitle,
+            x: -20
+        },
+        xAxis: {
+            title: {
+                text: data.xTitle
+            },
+            categories: data.categories
+        },
+        yAxis: {
+            title: {
+                text: data.yTitle
+            },
+            plotLines: [{
+                value: 0,
+                width: 1,
+                color: '#808080'
+            }]
+        },
+        tooltip: {
+            enabled: true,
+            valueSuffix: data.suffix
+        },
+        legend: {
+            layout: 'vertical',
+            align: 'right',
+            verticalAlign: 'middle',
+            borderWidth: 1
+        },
+        series: data.series
+
+    }));
+
+}
+
+function updateViewType(index) {
+
+    $("#scrollBed").css('marginLeft', -index * 324 + 'px');
+
+}
+
+function collectData() {
+
+    var form = document.forms['data-form'],
+        data = null;
+
+    if (currentChartType !== chartsConfig.length - 1) {
+
+        data = getSeriesAndCategories();
+        $.extend(data, getUserConfig());
+
+        //饼图数据格式
+    } else {
+        data = getSeriesForPieChart();
+        data.title = form['title'].value;
+        data.suffix = form['unit'].value;
+    }
+
+    return data;
+
+}
+
+/**
+ * 获取用户配置信息
+ */
+function getUserConfig() {
+
+    var form = document.forms['data-form'],
+        info = {
+            title: form['title'].value,
+            subTitle: form['sub-title'].value,
+            xTitle: form['x-title'].value,
+            yTitle: form['y-title'].value,
+            suffix: form['unit'].value,
+            //数据对齐方式
+            tableDataFormat: getTableDataFormat(),
+            //饼图提示文字
+            tip: $("#tipInput").val()
+        };
+
+    return info;
+
+}
+
+function setUserConfig(config) {
+
+    var form = document.forms['data-form'];
+
+    config.title && (form['title'].value = config.title);
+    config.subTitle && (form['sub-title'].value = config.subTitle);
+    config.xTitle && (form['x-title'].value = config.xTitle);
+    config.yTitle && (form['y-title'].value = config.yTitle);
+    config.suffix && (form['unit'].value = config.suffix);
+    config.dataFormat == "-1" && (form['charts-format'][1].checked = true);
+    config.tip && (form['tip'].value = config.tip);
+    currentChartType = config.chartType || 0;
+
+}
+
+function getSeriesAndCategories() {
+
+    var form = document.forms['data-form'],
+        series = [],
+        categories = [],
+        tmp = [],
+        tableData = getTableData();
+
+    //反转数据
+    if (getTableDataFormat() === "-1") {
+
+        for (var i = 0, len = tableData.length; i < len; i++) {
+
+            for (var j = 0, jlen = tableData[i].length; j < jlen; j++) {
+
+                if (!tmp[j]) {
+                    tmp[j] = [];
+                }
+
+                tmp[j][i] = tableData[i][j];
+
+            }
+
+        }
+
+        tableData = tmp;
+
+    }
+
+    categories = tableData[0].slice(1);
+
+    for (var i = 1, data; data = tableData[i]; i++) {
+
+        series.push({
+            name: data[0],
+            data: data.slice(1)
+        });
+
+    }
+
+    return {
+        series: series,
+        categories: categories
+    };
+
+}
+
+/*
+ * 获取数据源数据对齐方式
+ */
+function getTableDataFormat() {
+
+    var form = document.forms['data-form'],
+        items = form['charts-format'];
+
+    return items[0].checked ? items[0].value : items[1].value;
+
+}
+
+/*
+ * 禁用非饼图类型的配置项
+ */
+function disableNotPieConfig() {
+
+    updateConfigItem('disable');
+
+}
+
+/*
+ * 启用非饼图类型的配置项
+ */
+function enableNotPieConfig() {
+
+    updateConfigItem('enable');
+
+}
+
+function updateConfigItem(value) {
+
+    var table = $("#showTable")[0],
+        isDisable = value === 'disable' ? true : false;
+
+    //table中的input处理
+    for (var i = 2, row; row = table.rows[i]; i++) {
+
+        for (var j = 1, cell; cell = row.cells[j]; j++) {
+
+            $("input", cell).attr("disabled", isDisable);
+
+        }
+
+    }
+
+    //其他项处理
+    $("input.not-pie-item").attr("disabled", isDisable);
+    $("#tipInput").attr("disabled", !isDisable)
+
+}
+
+/*
+ * 获取饼图数据
+ * 饼图的数据只取第一行的
+ **/
+function getSeriesForPieChart() {
+
+    var series = {
+        type: 'pie',
+        name: $("#tipInput").val(),
+        data: []
+    },
+        tableData = getTableData();
+
+
+    for (var j = 1, jlen = tableData[0].length; j < jlen; j++) {
+
+        var title = tableData[0][j],
+            val = tableData[1][j];
+
+        series.data.push([title, val]);
+
+    }
+
+    return {
+        series: [series]
+    };
+
+}
+
+function getTableData() {
+
+    var table = document.getElementById("showTable"),
+        xCount = table.rows[0].cells.length - 1,
+        values = getTableInputValue();
+
+    for (var i = 0, value; value = values[i]; i++) {
+
+        tableData[Math.floor(i / xCount) + 1][i % xCount + 1] = values[i];
+
+    }
+
+    return tableData;
+
+}
+
+function getTableInputValue() {
+
+    var table = document.getElementById("showTable"),
+        inputs = table.getElementsByTagName("input"),
+        values = [];
+
+    for (var i = 0, input; input = inputs[i]; i++) {
+        values.push(input.value | 0);
+    }
+
+    return values;
+
+}
+
+function getCellValue(cell) {
+
+    var value = utils.trim((cell.innerText || cell.textContent || ''));
+
+    return value.replace(new RegExp(UE.dom.domUtils.fillChar, 'g'), '').replace(/^\s+|\s+$/g, '');
+
+}
+
+
+//dialog确认事件
+dialog.onok = function () {
+
+    //收集信息
+    var form = document.forms['data-form'],
+        info = getUserConfig();
+
+    //添加图表类型
+    info.chartType = currentChartType;
+
+    //同步表格数据到编辑器
+    syncTableData();
+
+    //执行图表命令
+    editor.execCommand('charts', info);
+
+};
+
+/*
+ * 同步图表编辑视图的表格数据到编辑器里的原始表格
+ */
+function syncTableData() {
+
+    var tableData = getTableData();
+
+    for (var i = 1, row; row = editorTable.rows[i]; i++) {
+
+        for (var j = 1, cell; cell = row.cells[j]; j++) {
+
+            cell.innerHTML = tableData[i][j];
+
+        }
+
+    }
+
+}

BIN
public/Ueditor/dialogs/charts/images/charts0.png


BIN
public/Ueditor/dialogs/charts/images/charts1.png


BIN
public/Ueditor/dialogs/charts/images/charts2.png


BIN
public/Ueditor/dialogs/charts/images/charts3.png


BIN
public/Ueditor/dialogs/charts/images/charts4.png


BIN
public/Ueditor/dialogs/charts/images/charts5.png


+ 43 - 0
public/Ueditor/dialogs/emotion/emotion.css

@@ -0,0 +1,43 @@
+.jd img{
+    background:transparent url(images/jxface2.gif?v=1.1) no-repeat scroll left top;
+    cursor:pointer;width:35px;height:35px;display:block;
+}
+.pp img{
+    background:transparent url(images/fface.gif?v=1.1) no-repeat scroll left top;
+    cursor:pointer;width:25px;height:25px;display:block;
+}
+.ldw img{
+    background:transparent url(images/wface.gif?v=1.1) no-repeat scroll left top;
+    cursor:pointer;width:35px;height:35px;display:block;
+}
+.tsj img{
+    background:transparent url(images/tface.gif?v=1.1) no-repeat scroll left top;
+    cursor:pointer;width:35px;height:35px;display:block;
+}
+.cat img{
+    background:transparent url(images/cface.gif?v=1.1) no-repeat scroll left top;
+    cursor:pointer;width:35px;height:35px;display:block;
+}
+.bb img{
+    background:transparent url(images/bface.gif?v=1.1) no-repeat scroll left top;
+    cursor:pointer;width:35px;height:35px;display:block;
+}
+.youa img{
+    background:transparent url(images/yface.gif?v=1.1) no-repeat scroll left top;
+    cursor:pointer;width:35px;height:35px;display:block;
+}
+
+.smileytable td {height: 37px;}
+#tabPanel{margin-left:5px;overflow: hidden;}
+#tabContent {float:left;background:#FFFFFF;}
+#tabContent div{display: none;width:480px;overflow:hidden;}
+#tabIconReview.show{left:17px;display:block;}
+.menuFocus{background:#ACCD3C;}
+.menuDefault{background:#FFFFFF;}
+#tabIconReview{position:absolute;left:406px;left:398px \9;top:41px;z-index:65533;width:90px;height:76px;}
+img.review{width:90px;height:76px;border:2px solid #9cb945;background:#FFFFFF;background-position:center;background-repeat:no-repeat;}
+
+.wrapper .tabbody{position:relative;float:left;clear:both;padding:10px;width: 95%;}
+.tabbody table{width: 100%;}
+.tabbody td{border:1px solid #BAC498;}
+.tabbody td span{display: block;zoom:1;padding:0 4px;}

+ 54 - 0
public/Ueditor/dialogs/emotion/emotion.html

@@ -0,0 +1,54 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <title></title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+    <meta name="robots" content="noindex, nofollow"/>
+    <script type="text/javascript" src="../internal.js"></script>
+    <link rel="stylesheet" type="text/css" href="emotion.css">
+</head>
+<body>
+<div id="tabPanel" class="wrapper">
+    <div id="tabHeads" class="tabhead">
+        <span><var id="lang_input_choice"></var></span>
+        <span><var id="lang_input_Tuzki"></var></span>
+        <span><var id="lang_input_lvdouwa"></var></span>
+        <span><var id="lang_input_BOBO"></var></span>
+        <span><var id="lang_input_babyCat"></var></span>
+        <span><var id="lang_input_bubble"></var></span>
+        <span><var id="lang_input_youa"></var></span>
+    </div>
+    <div id="tabBodys" class="tabbody">
+        <div id="tab0"></div>
+        <div id="tab1"></div>
+        <div id="tab2"></div>
+        <div id="tab3"></div>
+        <div id="tab4"></div>
+        <div id="tab5"></div>
+        <div id="tab6"></div>
+    </div>
+</div>
+<div id="tabIconReview">
+    <img id='faceReview' class='review' src="../../themes/default/images/spacer.gif"/>
+</div>
+<script type="text/javascript" src="emotion.js"></script>
+<script type="text/javascript">
+    var emotion = {
+        tabNum:7, //切换面板数量
+        SmilmgName:{ tab0:['j_00', 84], tab1:['t_00', 40], tab2:['w_00', 52], tab3:['B_00', 63], tab4:['C_00', 20], tab5:['i_f', 50], tab6:['y_00', 40] }, //图片前缀名
+        imageFolders:{ tab0:'jx2/', tab1:'tsj/', tab2:'ldw/', tab3:'bobo/', tab4:'babycat/', tab5:'face/', tab6:'youa/'}, //图片对应文件夹路径
+        imageCss:{tab0:'jd', tab1:'tsj', tab2:'ldw', tab3:'bb', tab4:'cat', tab5:'pp', tab6:'youa'}, //图片css类名
+        imageCssOffset:{tab0:35, tab1:35, tab2:35, tab3:35, tab4:35, tab5:25, tab6:35}, //图片偏移
+        SmileyInfor:{
+            tab0:['Kiss', 'Love', 'Yeah', '啊!', '背扭', '顶', '抖胸', '88', '汗', '瞌睡', '鲁拉', '拍砖', '揉脸', '生日快乐', '大笑', '瀑布汗~', '惊讶', '臭美', '傻笑', '抛媚眼', '发怒', '打酱油', '俯卧撑', '气愤', '?', '吻', '怒', '胜利', 'HI', 'KISS', '不说', '不要', '扯花', '大心', '顶', '大惊', '飞吻', '鬼脸', '害羞', '口水', '狂哭', '来', '发财了', '吃西瓜', '套牢', '害羞', '庆祝', '我来了', '敲打', '晕了', '胜利', '臭美', '被打了', '贪吃', '迎接', '酷', '微笑', '亲吻', '调皮', '惊恐', '耍酷', '发火', '害羞', '汗水', '大哭', '', '加油', '困', '你NB', '晕倒', '开心', '偷笑', '大哭', '滴汗', '叹气', '超赞', '??', '飞吻', '天使', '撒花', '生气', '被砸', '吓傻', '随意吐'],
+            tab1:['Kiss', 'Love', 'Yeah', '啊!', '背扭', '顶', '抖胸', '88', '汗', '瞌睡', '鲁拉', '拍砖', '揉脸', '生日快乐', '摊手', '睡觉', '瘫坐', '无聊', '星星闪', '旋转', '也不行', '郁闷', '正Music', '抓墙', '撞墙至死', '歪头', '戳眼', '飘过', '互相拍砖', '砍死你', '扔桌子', '少林寺', '什么?', '转头', '我爱牛奶', '我踢', '摇晃', '晕厥', '在笼子里', '震荡'],
+            tab2:['大笑', '瀑布汗~', '惊讶', '臭美', '傻笑', '抛媚眼', '发怒', '我错了', 'money', '气愤', '挑逗', '吻', '怒', '胜利', '委屈', '受伤', '说啥呢?', '闭嘴', '不', '逗你玩儿', '飞吻', '眩晕', '魔法', '我来了', '睡了', '我打', '闭嘴', '打', '打晕了', '刷牙', '爆揍', '炸弹', '倒立', '刮胡子', '邪恶的笑', '不要不要', '爱恋中', '放大仔细看', '偷窥', '超高兴', '晕', '松口气', '我跑', '享受', '修养', '哭', '汗', '啊~', '热烈欢迎', '打酱油', '俯卧撑', '?'],
+            tab3:['HI', 'KISS', '不说', '不要', '扯花', '大心', '顶', '大惊', '飞吻', '鬼脸', '害羞', '口水', '狂哭', '来', '泪眼', '流泪', '生气', '吐舌', '喜欢', '旋转', '再见', '抓狂', '汗', '鄙视', '拜', '吐血', '嘘', '打人', '蹦跳', '变脸', '扯肉', '吃To', '吃花', '吹泡泡糖', '大变身', '飞天舞', '回眸', '可怜', '猛抽', '泡泡', '苹果', '亲', '', '骚舞', '烧香', '睡', '套娃娃', '捅捅', '舞倒', '西红柿', '爱慕', '摇', '摇摆', '杂耍', '招财', '被殴', '被球闷', '大惊', '理想', '欧打', '呕吐', '碎', '吐痰'],
+            tab4:['发财了', '吃西瓜', '套牢', '害羞', '庆祝', '我来了', '敲打', '晕了', '胜利', '臭美', '被打了', '贪吃', '迎接', '酷', '顶', '幸运', '爱心', '躲', '送花', '选择'],
+            tab5:['微笑', '亲吻', '调皮', '惊讶', '耍酷', '发火', '害羞', '汗水', '大哭', '得意', '鄙视', '困', '夸奖', '晕倒', '疑问', '媒婆', '狂吐', '青蛙', '发愁', '亲吻', '', '爱心', '心碎', '玫瑰', '礼物', '哭', '奸笑', '可爱', '得意', '呲牙', '暴汗', '楚楚可怜', '困', '哭', '生气', '惊讶', '口水', '彩虹', '夜空', '太阳', '钱钱', '灯泡', '咖啡', '蛋糕', '音乐', '爱', '胜利', '赞', '鄙视', 'OK'],
+            tab6:['男兜', '女兜', '开心', '乖乖', '偷笑', '大笑', '抽泣', '大哭', '无奈', '滴汗', '叹气', '狂晕', '委屈', '超赞', '??', '疑问', '飞吻', '天使', '撒花', '生气', '被砸', '口水', '泪奔', '吓傻', '吐舌头', '点头', '随意吐', '旋转', '困困', '鄙视', '狂顶', '篮球', '再见', '欢迎光临', '恭喜发财', '稍等', '我在线', '恕不议价', '库房有货', '货在路上']
+        }
+    };
+</script>
+</body>
+</html>

+ 186 - 0
public/Ueditor/dialogs/emotion/emotion.js

@@ -0,0 +1,186 @@
+window.onload = function () {
+    editor.setOpt({
+        emotionLocalization:false
+    });
+
+    emotion.SmileyPath = editor.options.emotionLocalization === true ? 'images/' : "http://img.baidu.com/hi/";
+    emotion.SmileyBox = createTabList( emotion.tabNum );
+    emotion.tabExist = createArr( emotion.tabNum );
+
+    initImgName();
+    initEvtHandler( "tabHeads" );
+};
+
+function initImgName() {
+    for ( var pro in emotion.SmilmgName ) {
+        var tempName = emotion.SmilmgName[pro],
+                tempBox = emotion.SmileyBox[pro],
+                tempStr = "";
+
+        if ( tempBox.length ) return;
+        for ( var i = 1; i <= tempName[1]; i++ ) {
+            tempStr = tempName[0];
+            if ( i < 10 ) tempStr = tempStr + '0';
+            tempStr = tempStr + i + '.gif';
+            tempBox.push( tempStr );
+        }
+    }
+}
+
+function initEvtHandler( conId ) {
+    var tabHeads = $G( conId );
+    for ( var i = 0, j = 0; i < tabHeads.childNodes.length; i++ ) {
+        var tabObj = tabHeads.childNodes[i];
+        if ( tabObj.nodeType == 1 ) {
+            domUtils.on( tabObj, "click", (function ( index ) {
+                return function () {
+                    switchTab( index );
+                };
+            })( j ) );
+            j++;
+        }
+    }
+    switchTab( 0 );
+    $G( "tabIconReview" ).style.display = 'none';
+}
+
+function InsertSmiley( url, evt ) {
+    var obj = {
+        src:editor.options.emotionLocalization ? editor.options.UEDITOR_HOME_URL + "dialogs/emotion/" + url : url
+    };
+    obj._src = obj.src;
+    editor.execCommand( 'insertimage', obj );
+    if ( !evt.ctrlKey ) {
+        dialog.popup.hide();
+    }
+}
+
+function switchTab( index ) {
+
+    autoHeight( index );
+    if ( emotion.tabExist[index] == 0 ) {
+        emotion.tabExist[index] = 1;
+        createTab( 'tab' + index );
+    }
+    //获取呈现元素句柄数组
+    var tabHeads = $G( "tabHeads" ).getElementsByTagName( "span" ),
+            tabBodys = $G( "tabBodys" ).getElementsByTagName( "div" ),
+            i = 0, L = tabHeads.length;
+    //隐藏所有呈现元素
+    for ( ; i < L; i++ ) {
+        tabHeads[i].className = "";
+        tabBodys[i].style.display = "none";
+    }
+    //显示对应呈现元素
+    tabHeads[index].className = "focus";
+    tabBodys[index].style.display = "block";
+}
+
+function autoHeight( index ) {
+    var iframe = dialog.getDom( "iframe" ),
+            parent = iframe.parentNode.parentNode;
+    switch ( index ) {
+        case 0:
+            iframe.style.height = "380px";
+            parent.style.height = "392px";
+            break;
+        case 1:
+            iframe.style.height = "220px";
+            parent.style.height = "232px";
+            break;
+        case 2:
+            iframe.style.height = "260px";
+            parent.style.height = "272px";
+            break;
+        case 3:
+            iframe.style.height = "300px";
+            parent.style.height = "312px";
+            break;
+        case 4:
+            iframe.style.height = "140px";
+            parent.style.height = "152px";
+            break;
+        case 5:
+            iframe.style.height = "260px";
+            parent.style.height = "272px";
+            break;
+        case 6:
+            iframe.style.height = "230px";
+            parent.style.height = "242px";
+            break;
+        default:
+
+    }
+}
+
+
+function createTab( tabName ) {
+    var faceVersion = "?v=1.1", //版本号
+            tab = $G( tabName ), //获取将要生成的Div句柄
+            imagePath = emotion.SmileyPath + emotion.imageFolders[tabName], //获取显示表情和预览表情的路径
+            positionLine = 11 / 2, //中间数
+            iWidth = iHeight = 35, //图片长宽
+            iColWidth = 3, //表格剩余空间的显示比例
+            tableCss = emotion.imageCss[tabName],
+            cssOffset = emotion.imageCssOffset[tabName],
+            textHTML = ['<table class="smileytable">'],
+            i = 0, imgNum = emotion.SmileyBox[tabName].length, imgColNum = 11, faceImage,
+            sUrl, realUrl, posflag, offset, infor;
+
+    for ( ; i < imgNum; ) {
+        textHTML.push( '<tr>' );
+        for ( var j = 0; j < imgColNum; j++, i++ ) {
+            faceImage = emotion.SmileyBox[tabName][i];
+            if ( faceImage ) {
+                sUrl = imagePath + faceImage + faceVersion;
+                realUrl = imagePath + faceImage;
+                posflag = j < positionLine ? 0 : 1;
+                offset = cssOffset * i * (-1) - 1;
+                infor = emotion.SmileyInfor[tabName][i];
+
+                textHTML.push( '<td  class="' + tableCss + '"   border="1" width="' + iColWidth + '%" style="border-collapse:collapse;" align="center"  bgcolor="transparent" onclick="InsertSmiley(\'' + realUrl.replace( /'/g, "\\'" ) + '\',event)" onmouseover="over(this,\'' + sUrl + '\',\'' + posflag + '\')" onmouseout="out(this)">' );
+                textHTML.push( '<span>' );
+                textHTML.push( '<img  style="background-position:left ' + offset + 'px;" title="' + infor + '" src="' + emotion.SmileyPath + (editor.options.emotionLocalization ? '0.gif" width="' : 'default/0.gif" width="') + iWidth + '" height="' + iHeight + '"></img>' );
+                textHTML.push( '</span>' );
+            } else {
+                textHTML.push( '<td width="' + iColWidth + '%"   bgcolor="#FFFFFF">' );
+            }
+            textHTML.push( '</td>' );
+        }
+        textHTML.push( '</tr>' );
+    }
+    textHTML.push( '</table>' );
+    textHTML = textHTML.join( "" );
+    tab.innerHTML = textHTML;
+}
+
+function over( td, srcPath, posFlag ) {
+    td.style.backgroundColor = "#ACCD3C";
+    $G( 'faceReview' ).style.backgroundImage = "url(" + srcPath + ")";
+    if ( posFlag == 1 ) $G( "tabIconReview" ).className = "show";
+    $G( "tabIconReview" ).style.display = 'block';
+}
+
+function out( td ) {
+    td.style.backgroundColor = "transparent";
+    var tabIconRevew = $G( "tabIconReview" );
+    tabIconRevew.className = "";
+    tabIconRevew.style.display = 'none';
+}
+
+function createTabList( tabNum ) {
+    var obj = {};
+    for ( var i = 0; i < tabNum; i++ ) {
+        obj["tab" + i] = [];
+    }
+    return obj;
+}
+
+function createArr( tabNum ) {
+    var arr = [];
+    for ( var i = 0; i < tabNum; i++ ) {
+        arr[i] = 0;
+    }
+    return arr;
+}
+

BIN
public/Ueditor/dialogs/emotion/images/0.gif


BIN
public/Ueditor/dialogs/emotion/images/bface.gif


BIN
public/Ueditor/dialogs/emotion/images/cface.gif


BIN
public/Ueditor/dialogs/emotion/images/fface.gif


BIN
public/Ueditor/dialogs/emotion/images/jxface2.gif


BIN
public/Ueditor/dialogs/emotion/images/neweditor-tab-bg.png


BIN
public/Ueditor/dialogs/emotion/images/tface.gif


BIN
public/Ueditor/dialogs/emotion/images/wface.gif


BIN
public/Ueditor/dialogs/emotion/images/yface.gif


+ 89 - 0
public/Ueditor/dialogs/gmap/gmap.html

@@ -0,0 +1,89 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title></title>
+    <script type="text/javascript" src="../internal.js"></script>
+    <style type="text/css">
+        .content{width:530px; height: 350px;margin: 10px auto;}
+        .content table{width: 100%}
+        .content table td{vertical-align: middle;}
+        #address{width:220px;height:21px;background: #FFF;border:1px solid #d7d7d7; line-height: 21px;}
+    </style>
+    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
+</head>
+<body>
+<div class="content">
+    <table>
+        <tr>
+            <td><label for="address"><var id="lang_input_address"></var></label></td>
+            <td><input id="address" type="text" /></td>
+            <td><a id="doSearch" href="javascript:void(0)" class="button"><var id="lang_input_search"></var></a></td>
+        </tr>
+    </table>
+    <div id="container" style="width: 100%; height: 340px;margin: 5px auto; border: 1px solid gray;"></div>
+</div>
+<script type="text/javascript">
+    domUtils.on(window,"load",function(){
+        var map = new google.maps.Map(document.getElementById('container'), {
+                zoom: 3,
+                streetViewControl: false,
+                scaleControl: true,
+                mapTypeId: google.maps.MapTypeId.ROADMAP
+            });
+            var imgcss;
+            var marker = new google.maps.Marker({
+                map: map,
+                draggable: true
+            });
+            function doSearch(){
+                var address = document.getElementById('address').value;
+                var geocoder = new google.maps.Geocoder();
+                geocoder.geocode( { 'address': address}, function (results, status) {
+                    if (status == google.maps.GeocoderStatus.OK) {
+                        var bounds = results[0].geometry.viewport;
+                        map.fitBounds(bounds);
+                        marker.setPosition(results[0].geometry.location);
+                        marker.setTitle(address);
+                    } else alert(lang.searchError);
+                });
+            }
+            $G('address').onkeydown = function (evt){
+                evt = evt || event;
+                if (evt.keyCode == 13) {
+                    doSearch();
+                }
+            };
+            $G("doSearch").onclick = doSearch;
+            dialog.onok = function (){
+                var center = map.getCenter();
+                var point = marker.getPosition();
+                var url = "http://maps.googleapis.com/maps/api/staticmap?center=" + center.lat() + ',' + center.lng() + "&zoom=" + map.zoom + "&size=520x340&maptype=" + map.getMapTypeId() + "&markers=" + point.lat() + ',' + point.lng() + "&sensor=false";
+                editor.execCommand('inserthtml', '<img width="520" height="340" src="' + url + '"' + (imgcss ? ' style="' + imgcss + '"' :'') + '/>');
+            };
+
+            function getPars(str,par){
+                var reg = new RegExp(par+"=((\\d+|[.,])*)","g");
+                return reg.exec(str)[1];
+            }
+            var img = editor.selection.getRange().getClosedNode();
+            if(img && img.src.indexOf("http://maps.googleapis.com/maps/api/staticmap")!=-1){
+                var url = img.getAttribute("src");
+                var centers = getPars(url,"center").split(",");
+                point = new google.maps.LatLng(Number(centers[0]),Number(centers[1]));
+                map.setCenter(point);
+                map.setZoom(Number(getPars(url,"zoom")));
+                centers = getPars(url,"markers").split(",");
+                marker.setPosition(new google.maps.LatLng(Number(centers[0]),Number(centers[1])));
+                imgcss = img.style.cssText;
+            }else{
+                setTimeout(function(){
+                    doSearch();
+                },30)
+            }
+    });
+
+</script>
+</body>
+</html>

+ 7 - 0
public/Ueditor/dialogs/help/help.css

@@ -0,0 +1,7 @@
+.wrapper{width: 370px;margin: 10px auto;zoom: 1;}
+.tabbody{height: 360px;}
+.tabbody .panel{width:100%;height: 360px;position: absolute;background: #fff;}
+.tabbody .panel h1{font-size:26px;margin: 5px 0 0 5px;}
+.tabbody .panel p{font-size:12px;margin: 5px 0 0 5px;}
+.tabbody table{width:90%;line-height: 20px;margin: 5px 0 0 5px;;}
+.tabbody table thead{font-weight: bold;line-height: 25px;}

+ 82 - 0
public/Ueditor/dialogs/help/help.html

@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title>帮助</title>
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
+    <script type="text/javascript" src="../internal.js"></script>
+    <link rel="stylesheet" type="text/css" href="help.css">
+</head>
+<body>
+<div class="wrapper" id="helptab">
+    <div id="tabHeads" class="tabhead">
+        <span class="focus" tabsrc="about"><var id="lang_input_about"></var></span>
+        <span tabsrc="shortcuts"><var id="lang_input_shortcuts"></var></span>
+    </div>
+    <div id="tabBodys" class="tabbody">
+        <div id="about" class="panel">
+            <h1>UEditor</h1>
+            <p id="version"></p>
+            <p><var id="lang_input_introduction"></var></p>
+        </div>
+        <div id="shortcuts" class="panel">
+            <table>
+                <thead>
+                <tr>
+                    <td><var id="lang_Txt_shortcuts"></var></td>
+                    <td><var id="lang_Txt_func"></var></td>
+                </tr>
+                </thead>
+                <tbody>
+                <tr>
+                    <td>ctrl+b</td>
+                    <td><var id="lang_Txt_bold"></var></td>
+                </tr>
+                <tr>
+                    <td>ctrl+c</td>
+                    <td><var id="lang_Txt_copy"></var></td>
+                </tr>
+                <tr>
+                    <td>ctrl+x</td>
+                    <td><var id="lang_Txt_cut"></var></td>
+                </tr>
+                <tr>
+                    <td>ctrl+v</td>
+                    <td><var id="lang_Txt_Paste"></var></td>
+                </tr>
+                <tr>
+                    <td>ctrl+y</td>
+                    <td><var id="lang_Txt_undo"></var></td>
+                </tr>
+                <tr>
+                    <td>ctrl+z</td>
+                    <td><var id="lang_Txt_redo"></var></td>
+                </tr>
+                <tr>
+                    <td>ctrl+i</td>
+                    <td><var id="lang_Txt_italic"></var></td>
+                </tr>
+                <tr>
+                    <td>ctrl+u</td>
+                    <td><var id="lang_Txt_underline"></var></td>
+                </tr>
+                <tr>
+                    <td>ctrl+a</td>
+                    <td><var id="lang_Txt_selectAll"></var></td>
+                </tr>
+                <tr>
+                    <td>shift+enter</td>
+                    <td><var id="lang_Txt_visualEnter"></var></td>
+                </tr>
+                <tr>
+                    <td>alt+z</td>
+                    <td><var id="lang_Txt_fullscreen"></var></td>
+                </tr>
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>
+<script type="text/javascript" src="help.js"></script>
+</body>
+</html>

+ 56 - 0
public/Ueditor/dialogs/help/help.js

@@ -0,0 +1,56 @@
+/**
+ * Created with JetBrains PhpStorm.
+ * User: xuheng
+ * Date: 12-9-26
+ * Time: 下午1:06
+ * To change this template use File | Settings | File Templates.
+ */
+/**
+ * tab点击处理事件
+ * @param tabHeads
+ * @param tabBodys
+ * @param obj
+ */
+function clickHandler( tabHeads,tabBodys,obj ) {
+    //head样式更改
+    for ( var k = 0, len = tabHeads.length; k < len; k++ ) {
+        tabHeads[k].className = "";
+    }
+    obj.className = "focus";
+    //body显隐
+    var tabSrc = obj.getAttribute( "tabSrc" );
+    for ( var j = 0, length = tabBodys.length; j < length; j++ ) {
+        var body = tabBodys[j],
+            id = body.getAttribute( "id" );
+        body.onclick = function(){
+            this.style.zoom = 1;
+        };
+        if ( id != tabSrc ) {
+            body.style.zIndex = 1;
+        } else {
+            body.style.zIndex = 200;
+        }
+    }
+
+}
+
+/**
+ * TAB切换
+ * @param tabParentId  tab的父节点ID或者对象本身
+ */
+function switchTab( tabParentId ) {
+    var tabElements = $G( tabParentId ).children,
+        tabHeads = tabElements[0].children,
+        tabBodys = tabElements[1].children;
+
+    for ( var i = 0, length = tabHeads.length; i < length; i++ ) {
+        var head = tabHeads[i];
+        if ( head.className === "focus" )clickHandler(tabHeads,tabBodys, head );
+        head.onclick = function () {
+            clickHandler(tabHeads,tabBodys,this);
+        }
+    }
+}
+switchTab("helptab");
+
+document.getElementById('version').innerHTML = parent.UE.version;

+ 894 - 0
public/Ueditor/dialogs/image/image.css

@@ -0,0 +1,894 @@
+@charset "utf-8";
+/* dialog样式 */
+.wrapper {
+    zoom: 1;
+    width: 630px;
+    *width: 626px;
+    height: 380px;
+    margin: 0 auto;
+    padding: 10px;
+    position: relative;
+    font-family: sans-serif;
+}
+
+/*tab样式框大小*/
+.tabhead {
+    float:left;
+}
+.tabbody {
+    width: 100%;
+    height: 346px;
+    position: relative;
+    clear: both;
+}
+
+.tabbody .panel {
+    position: absolute;
+    width: 0;
+    height: 0;
+    background: #fff;
+    overflow: hidden;
+    display: none;
+}
+
+.tabbody .panel.focus {
+    width: 100%;
+    height: 346px;
+    display: block;
+}
+
+/* 图片对齐方式 */
+.alignBar{
+    float:right;
+    margin-top: 5px;
+    position: relative;
+}
+
+.alignBar .algnLabel{
+    float:left;
+    height: 20px;
+    line-height: 20px;
+}
+
+.alignBar #alignIcon{
+    zoom:1;
+    _display: inline;
+    display: inline-block;
+    position: relative;
+}
+.alignBar #alignIcon span{
+    float: left;
+    cursor: pointer;
+    display: block;
+    width: 19px;
+    height: 17px;
+    margin-right: 3px;
+    margin-left: 3px;
+    background-image: url(images/alignicon.jpg);
+}
+.alignBar #alignIcon .none-align{
+    background-position: 0 -18px;
+}
+.alignBar #alignIcon .left-align{
+    background-position: -20px -18px;
+}
+.alignBar #alignIcon .right-align{
+    background-position: -40px -18px;
+}
+.alignBar #alignIcon .center-align{
+    background-position: -60px -18px;
+}
+.alignBar #alignIcon .none-align.focus{
+    background-position: 0 0;
+}
+.alignBar #alignIcon .left-align.focus{
+    background-position: -20px 0;
+}
+.alignBar #alignIcon .right-align.focus{
+    background-position: -40px 0;
+}
+.alignBar #alignIcon .center-align.focus{
+    background-position: -60px 0;
+}
+
+
+
+
+/* 远程图片样式 */
+#remote {
+    z-index: 200;
+}
+
+#remote .top{
+    width: 100%;
+    margin-top: 25px;
+}
+#remote .left{
+    display: block;
+    float: left;
+    width: 300px;
+    height:10px;
+}
+#remote .right{
+    display: block;
+    float: right;
+    width: 300px;
+    height:10px;
+}
+#remote .row{
+    margin-left: 20px;
+    clear: both;
+    height: 40px;
+}
+
+#remote .row label{
+    text-align: center;
+    width: 50px;
+    zoom:1;
+    _display: inline;
+    display:inline-block;
+    vertical-align: middle;
+}
+#remote .row label.algnLabel{
+    float: left;
+
+}
+
+#remote input.text{
+    width: 150px;
+    padding: 3px 6px;
+    font-size: 14px;
+    line-height: 1.42857143;
+    color: #555;
+    background-color: #fff;
+    background-image: none;
+    border: 1px solid #ccc;
+    border-radius: 4px;
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+    -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+    transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+#remote input.text:focus {
+    border-color: #66afe9;
+    outline: 0;
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
+}
+#remote #url{
+    width: 500px;
+    margin-bottom: 2px;
+}
+#remote #width,
+#remote #height{
+    width: 20px;
+    margin-left: 2px;
+    margin-right: 2px;
+}
+#remote #border,
+#remote #vhSpace,
+#remote #title{
+    width: 180px;
+    margin-right: 5px;
+}
+#remote #lock{
+}
+#remote #lockicon{
+    zoom: 1;
+    _display:inline;
+    display: inline-block;
+    width: 20px;
+    height: 20px;
+    background: url("../../themes/default/images/lock.gif") -13px -13px no-repeat;
+    vertical-align: middle;
+}
+#remote #preview{
+    clear: both;
+    width: 260px;
+    height: 240px;
+    z-index: 9999;
+    margin-top: 10px;
+    background-color: #eee;
+    overflow: hidden;
+}
+
+/* 上传图片 */
+.tabbody #upload.panel {
+    width: 0;
+    height: 0;
+    overflow: hidden;
+    position: absolute !important;
+    clip: rect(1px, 1px, 1px, 1px);
+    background: #fff;
+    display: block;
+}
+
+.tabbody #upload.panel.focus {
+    width: 100%;
+    height: 346px;
+    display: block;
+    clip: auto;
+}
+
+#upload .queueList {
+    margin: 0;
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    overflow: hidden;
+}
+
+#upload p {
+    margin: 0;
+}
+
+.element-invisible {
+    width: 0 !important;
+    height: 0 !important;
+    border: 0;
+    padding: 0;
+    margin: 0;
+    overflow: hidden;
+    position: absolute !important;
+    clip: rect(1px, 1px, 1px, 1px);
+}
+
+#upload .placeholder {
+    margin: 10px;
+    border: 2px dashed #e6e6e6;
+    *border: 0px dashed #e6e6e6;
+    height: 172px;
+    padding-top: 150px;
+    text-align: center;
+    background: url(images/image.png) center 70px no-repeat;
+    color: #cccccc;
+    font-size: 18px;
+    position: relative;
+    top:0;
+    *top: 10px;
+}
+
+#upload .placeholder .webuploader-pick {
+    font-size: 18px;
+    background: #00b7ee;
+    border-radius: 3px;
+    line-height: 44px;
+    padding: 0 30px;
+    *width: 120px;
+    color: #fff;
+    display: inline-block;
+    margin: 0 auto 20px auto;
+    cursor: pointer;
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+}
+
+#upload .placeholder .webuploader-pick-hover {
+    background: #00a2d4;
+}
+
+
+#filePickerContainer {
+    text-align: center;
+}
+
+#upload .placeholder .flashTip {
+    color: #666666;
+    font-size: 12px;
+    position: absolute;
+    width: 100%;
+    text-align: center;
+    bottom: 20px;
+}
+
+#upload .placeholder .flashTip a {
+    color: #0785d1;
+    text-decoration: none;
+}
+
+#upload .placeholder .flashTip a:hover {
+    text-decoration: underline;
+}
+
+#upload .placeholder.webuploader-dnd-over {
+    border-color: #999999;
+}
+
+#upload .filelist {
+    list-style: none;
+    margin: 0;
+    padding: 0;
+    overflow-x: hidden;
+    overflow-y: auto;
+    position: relative;
+    height: 300px;
+}
+
+#upload .filelist:after {
+    content: '';
+    display: block;
+    width: 0;
+    height: 0;
+    overflow: hidden;
+    clear: both;
+    position: relative;
+}
+
+#upload .filelist li {
+    width: 113px;
+    height: 113px;
+    background: url(images/bg.png);
+    text-align: center;
+    margin: 9px 0 0 9px;
+    *margin: 6px 0 0 6px;
+    position: relative;
+    display: block;
+    float: left;
+    overflow: hidden;
+    font-size: 12px;
+}
+
+#upload .filelist li p.log {
+    position: relative;
+    top: -45px;
+}
+
+#upload .filelist li p.title {
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
+    top: 5px;
+    text-indent: 5px;
+    text-align: left;
+}
+
+#upload .filelist li p.progress {
+    position: absolute;
+    width: 100%;
+    bottom: 0;
+    left: 0;
+    height: 8px;
+    overflow: hidden;
+    z-index: 50;
+    margin: 0;
+    border-radius: 0;
+    background: none;
+    -webkit-box-shadow: 0 0 0;
+}
+
+#upload .filelist li p.progress span {
+    display: none;
+    overflow: hidden;
+    width: 0;
+    height: 100%;
+    background: #1483d8 url(images/progress.png) repeat-x;
+
+    -webit-transition: width 200ms linear;
+    -moz-transition: width 200ms linear;
+    -o-transition: width 200ms linear;
+    -ms-transition: width 200ms linear;
+    transition: width 200ms linear;
+
+    -webkit-animation: progressmove 2s linear infinite;
+    -moz-animation: progressmove 2s linear infinite;
+    -o-animation: progressmove 2s linear infinite;
+    -ms-animation: progressmove 2s linear infinite;
+    animation: progressmove 2s linear infinite;
+
+    -webkit-transform: translateZ(0);
+}
+
+@-webkit-keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+@-moz-keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+@keyframes progressmove {
+    0% {
+        background-position: 0 0;
+    }
+    100% {
+        background-position: 17px 0;
+    }
+}
+
+#upload .filelist li p.imgWrap {
+    position: relative;
+    z-index: 2;
+    line-height: 113px;
+    vertical-align: middle;
+    overflow: hidden;
+    width: 113px;
+    height: 113px;
+
+    -webkit-transform-origin: 50% 50%;
+    -moz-transform-origin: 50% 50%;
+    -o-transform-origin: 50% 50%;
+    -ms-transform-origin: 50% 50%;
+    transform-origin: 50% 50%;
+
+    -webit-transition: 200ms ease-out;
+    -moz-transition: 200ms ease-out;
+    -o-transition: 200ms ease-out;
+    -ms-transition: 200ms ease-out;
+    transition: 200ms ease-out;
+}
+
+#upload .filelist li img {
+    width: 100%;
+}
+
+#upload .filelist li p.error {
+    background: #f43838;
+    color: #fff;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    height: 28px;
+    line-height: 28px;
+    width: 100%;
+    z-index: 100;
+    display:none;
+}
+
+#upload .filelist li .success {
+    display: block;
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    height: 40px;
+    width: 100%;
+    z-index: 200;
+    background: url(images/success.png) no-repeat right bottom;
+    background: url(images/success.gif) no-repeat right bottom \9;
+}
+
+#upload .filelist li.filePickerBlock {
+    width: 113px;
+    height: 113px;
+    background: url(images/image.png) no-repeat center 12px;
+    border: 1px solid #eeeeee;
+    border-radius: 0;
+}
+#upload .filelist li.filePickerBlock div.webuploader-pick  {
+    width: 100%;
+    height: 100%;
+    margin: 0;
+    padding: 0;
+    opacity: 0;
+    background: none;
+    font-size: 0;
+}
+
+#upload .filelist div.file-panel {
+    position: absolute;
+    height: 0;
+    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0;
+    background: rgba(0, 0, 0, 0.5);
+    width: 100%;
+    top: 0;
+    left: 0;
+    overflow: hidden;
+    z-index: 300;
+}
+
+#upload .filelist div.file-panel span {
+    width: 24px;
+    height: 24px;
+    display: inline;
+    float: right;
+    text-indent: -9999px;
+    overflow: hidden;
+    background: url(images/icons.png) no-repeat;
+    background: url(images/icons.gif) no-repeat \9;
+    margin: 5px 1px 1px;
+    cursor: pointer;
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+
+#upload .filelist div.file-panel span.rotateLeft {
+    display:none;
+    background-position: 0 -24px;
+}
+
+#upload .filelist div.file-panel span.rotateLeft:hover {
+    background-position: 0 0;
+}
+
+#upload .filelist div.file-panel span.rotateRight {
+    display:none;
+    background-position: -24px -24px;
+}
+
+#upload .filelist div.file-panel span.rotateRight:hover {
+    background-position: -24px 0;
+}
+
+#upload .filelist div.file-panel span.cancel {
+    background-position: -48px -24px;
+}
+
+#upload .filelist div.file-panel span.cancel:hover {
+    background-position: -48px 0;
+}
+
+#upload .statusBar {
+    height: 45px;
+    border-bottom: 1px solid #dadada;
+    margin: 0 10px;
+    padding: 0;
+    line-height: 45px;
+    vertical-align: middle;
+    position: relative;
+}
+
+#upload .statusBar .progress {
+    border: 1px solid #1483d8;
+    width: 198px;
+    background: #fff;
+    height: 18px;
+    position: absolute;
+    top: 12px;
+    display: none;
+    text-align: center;
+    line-height: 18px;
+    color: #6dbfff;
+    margin: 0 10px 0 0;
+}
+#upload .statusBar .progress span.percentage {
+    width: 0;
+    height: 100%;
+    left: 0;
+    top: 0;
+    background: #1483d8;
+    position: absolute;
+}
+#upload .statusBar .progress span.text {
+    position: relative;
+    z-index: 10;
+}
+
+#upload .statusBar .info {
+    display: inline-block;
+    font-size: 14px;
+    color: #666666;
+}
+
+#upload .statusBar .btns {
+    position: absolute;
+    top: 7px;
+    right: 0;
+    line-height: 30px;
+}
+
+#filePickerBtn {
+    display: inline-block;
+    float: left;
+}
+#upload .statusBar .btns .webuploader-pick,
+#upload .statusBar .btns .uploadBtn,
+#upload .statusBar .btns .uploadBtn.state-uploading,
+#upload .statusBar .btns .uploadBtn.state-paused {
+    background: #ffffff;
+    border: 1px solid #cfcfcf;
+    color: #565656;
+    padding: 0 18px;
+    display: inline-block;
+    border-radius: 3px;
+    margin-left: 10px;
+    cursor: pointer;
+    font-size: 14px;
+    float: left;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+}
+#upload .statusBar .btns .webuploader-pick-hover,
+#upload .statusBar .btns .uploadBtn:hover,
+#upload .statusBar .btns .uploadBtn.state-uploading:hover,
+#upload .statusBar .btns .uploadBtn.state-paused:hover {
+    background: #f0f0f0;
+}
+
+#upload .statusBar .btns .uploadBtn,
+#upload .statusBar .btns .uploadBtn.state-paused{
+    background: #00b7ee;
+    color: #fff;
+    border-color: transparent;
+}
+#upload .statusBar .btns .uploadBtn:hover,
+#upload .statusBar .btns .uploadBtn.state-paused:hover{
+    background: #00a2d4;
+}
+
+#upload .statusBar .btns .uploadBtn.disabled {
+    pointer-events: none;
+    filter:alpha(opacity=60);
+    -moz-opacity:0.6;
+    -khtml-opacity: 0.6;
+    opacity: 0.6;
+}
+
+
+
+/* 图片管理样式 */
+#online {
+    width: 100%;
+    height: 336px;
+    padding: 10px 0 0 0;
+}
+#online #imageList{
+    width: 100%;
+    height: 100%;
+    overflow-x: hidden;
+    overflow-y: auto;
+    position: relative;
+}
+#online ul {
+    display: block;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+#online li {
+    float: left;
+    display: block;
+    list-style: none;
+    padding: 0;
+    width: 113px;
+    height: 113px;
+    margin: 0 0 9px 9px;
+    *margin: 0 0 6px 6px;
+    background-color: #eee;
+    overflow: hidden;
+    cursor: pointer;
+    position: relative;
+}
+#online li.clearFloat {
+    float: none;
+    clear: both;
+    display: block;
+    width:0;
+    height:0;
+    margin: 0;
+    padding: 0;
+}
+#online li img {
+    cursor: pointer;
+}
+#online li .icon {
+    cursor: pointer;
+    width: 113px;
+    height: 113px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 2;
+    border: 0;
+    background-repeat: no-repeat;
+}
+#online li .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+}
+#online li.selected .icon {
+    background-image: url(images/success.png);
+    background-image: url(images/success.gif)\9;
+    background-position: 75px 75px;
+}
+#online li.selected .icon:hover {
+    width: 107px;
+    height: 107px;
+    border: 3px solid #1094fa;
+    background-position: 72px 72px;
+}
+
+
+/* 图片搜索样式 */
+#search .searchBar {
+    width: 100%;
+    height: 30px;
+    margin: 10px 0 5px 0;
+    padding: 0;
+}
+
+#search input.text{
+    width: 150px;
+    padding: 3px 6px;
+    font-size: 14px;
+    line-height: 1.42857143;
+    color: #555;
+    background-color: #fff;
+    background-image: none;
+    border: 1px solid #ccc;
+    border-radius: 4px;
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
+    -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+    transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+#search input.text:focus {
+    border-color: #66afe9;
+    outline: 0;
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
+}
+#search input.searchTxt {
+    margin-left:5px;
+    padding-left: 5px;
+    background: #FFF;
+    width: 300px;
+    *width: 260px;
+    height: 21px;
+    line-height: 21px;
+    float: left;
+    dislay: block;
+}
+
+#search .searchType {
+    width: 65px;
+    height: 28px;
+    padding:0;
+    line-height: 28px;
+    border: 1px solid #d7d7d7;
+    border-radius: 0;
+    vertical-align: top;
+    margin-left: 5px;
+    float: left;
+    dislay: block;
+}
+
+#search #searchBtn,
+#search #searchReset {
+    display: inline-block;
+    margin-bottom: 0;
+    margin-right: 5px;
+    padding: 4px 10px;
+    font-weight: 400;
+    text-align: center;
+    vertical-align: middle;
+    cursor: pointer;
+    background-image: none;
+    border: 1px solid transparent;
+    white-space: nowrap;
+    font-size: 14px;
+    border-radius: 4px;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    vertical-align: top;
+    float: right;
+}
+
+#search #searchBtn {
+    color: white;
+    border-color: #285e8e;
+    background-color: #3b97d7;
+}
+#search #searchReset {
+    color: #333;
+    border-color: #ccc;
+    background-color: #fff;
+}
+#search #searchBtn:hover {
+    background-color: #3276b1;
+}
+#search #searchReset:hover {
+    background-color: #eee;
+}
+
+#search .msg {
+    margin-left: 5px;
+}
+
+#search .searchList{
+    width: 100%;
+    height: 300px;
+    overflow: hidden;
+    clear: both;
+}
+#search .searchList ul{
+    margin:0;
+    padding:0;
+    list-style:none;
+    clear: both;
+    width: 100%;
+    height: 100%;
+    overflow-x: hidden;
+    overflow-y: auto;
+    zoom: 1;
+    position: relative;
+}
+
+#search .searchList li {
+    list-style:none;
+    float: left;
+    display: block;
+    width: 115px;
+    margin: 5px 10px 5px 20px;
+    *margin: 5px 10px 5px 15px;
+    padding:0;
+    font-size: 12px;
+    box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
+    -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
+    -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
+    position: relative;
+    vertical-align: top;
+    text-align: center;
+    overflow: hidden;
+    cursor: pointer;
+    filter: alpha(Opacity=100);
+    -moz-opacity: 1;
+    opacity: 1;
+    border: 2px solid #eee;
+}
+
+#search .searchList li.selected {
+    filter: alpha(Opacity=40);
+    -moz-opacity: 0.4;
+    opacity: 0.4;
+    border: 2px solid #00a0e9;
+}
+
+#search .searchList li p {
+    background-color: #eee;
+    margin: 0;
+    padding: 0;
+    position: relative;
+    width:100%;
+    height:115px;
+    overflow: hidden;
+}
+
+#search .searchList li p img {
+    cursor: pointer;
+    border: 0;
+}
+
+#search .searchList li a {
+    color: #999;
+    border-top: 1px solid #F2F2F2;
+    background: #FAFAFA;
+    text-align: center;
+    display: block;
+    padding: 0 5px;
+    width: 105px;
+    height:32px;
+    line-height:32px;
+    white-space:nowrap;
+    text-overflow:ellipsis;
+    text-decoration: none;
+    overflow: hidden;
+    word-break: break-all;
+}
+
+#search .searchList a:hover {
+    text-decoration: underline;
+    color: #333;
+}
+#search .searchList .clearFloat{
+    clear: both;
+}

+ 120 - 0
public/Ueditor/dialogs/image/image.html

@@ -0,0 +1,120 @@
+<!doctype html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>ueditor图片对话框</title>
+    <script type="text/javascript" src="../internal.js"></script>
+
+    <!-- jquery -->
+    <script type="text/javascript" src="../../third-party/jquery-1.10.2.min.js"></script>
+
+    <!-- webuploader -->
+    <script src="../../third-party/webuploader/webuploader.min.js"></script>
+    <link rel="stylesheet" type="text/css" href="../../third-party/webuploader/webuploader.css">
+
+    <!-- image dialog -->
+    <link rel="stylesheet" href="image.css" type="text/css" />
+</head>
+<body>
+
+    <div class="wrapper">
+        <div id="tabhead" class="tabhead">
+            <span class="tab" data-content-id="remote"><var id="lang_tab_remote"></var></span>
+            <span class="tab focus" data-content-id="upload"><var id="lang_tab_upload"></var></span>
+            <span class="tab" data-content-id="online"><var id="lang_tab_online"></var></span>
+            <span class="tab" data-content-id="search"><var id="lang_tab_search"></var></span>
+        </div>
+        <div class="alignBar">
+            <label class="algnLabel"><var id="lang_input_align"></var></label>
+                    <span id="alignIcon">
+                        <span id="noneAlign" class="none-align focus" data-align="none"></span>
+                        <span id="leftAlign" class="left-align" data-align="left"></span>
+                        <span id="rightAlign" class="right-align" data-align="right"></span>
+                        <span id="centerAlign" class="center-align" data-align="center"></span>
+                    </span>
+            <input id="align" name="align" type="hidden" value="none"/>
+        </div>
+        <div id="tabbody" class="tabbody">
+
+            <!-- 远程图片 -->
+            <div id="remote" class="panel">
+                <div class="top">
+                    <div class="row">
+                        <label for="url"><var id="lang_input_url"></var></label>
+                        <span><input class="text" id="url" type="text"/></span>
+                    </div>
+                </div>
+                <div class="left">
+                    <div class="row">
+                        <label><var id="lang_input_size"></var></label>
+                        <span><var id="lang_input_width">&nbsp;&nbsp;</var><input class="text" type="text" id="width"/>px </span>
+                        <span><var id="lang_input_height">&nbsp;&nbsp;</var><input class="text" type="text" id="height"/>px </span>
+                        <span><input id="lock" type="checkbox" disabled="disabled"><span id="lockicon"></span></span>
+                    </div>
+                    <div class="row">
+                        <label><var id="lang_input_border"></var></label>
+                        <span><input class="text" type="text" id="border"/>px </span>
+                    </div>
+                    <div class="row">
+                        <label><var id="lang_input_vhspace"></var></label>
+                        <span><input class="text" type="text" id="vhSpace"/>px </span>
+                    </div>
+                    <div class="row">
+                        <label><var id="lang_input_title"></var></label>
+                        <span><input class="text" type="text" id="title"/></span>
+                    </div>
+                </div>
+                <div class="right"><div id="preview"></div></div>
+            </div>
+
+            <!-- 上传图片 -->
+            <div id="upload" class="panel focus">
+                <div id="queueList" class="queueList">
+                    <div class="statusBar element-invisible">
+                        <div class="progress">
+                            <span class="text">0%</span>
+                            <span class="percentage"></span>
+                        </div><div class="info"></div>
+                        <div class="btns">
+                            <div id="filePickerBtn"></div>
+                            <div class="uploadBtn"><var id="lang_start_upload"></var></div>
+                        </div>
+                    </div>
+                    <div id="dndArea" class="placeholder">
+                        <div class="filePickerContainer">
+                            <div id="filePickerReady"></div>
+                        </div>
+                    </div>
+                    <ul class="filelist element-invisible">
+                        <li id="filePickerBlock" class="filePickerBlock"></li>
+                    </ul>
+                </div>
+            </div>
+
+            <!-- 在线图片 -->
+            <div id="online" class="panel">
+                <div id="imageList"><var id="lang_imgLoading"></var></div>
+            </div>
+
+            <!-- 搜索图片 -->
+            <div id="search" class="panel">
+                <div class="searchBar">
+                    <input id="searchTxt" class="searchTxt text" type="text" />
+                    <select id="searchType" class="searchType">
+                        <option value="&s=4&z=0"></option>
+                        <option value="&s=1&z=19"></option>
+                        <option value="&s=2&z=0"></option>
+                        <option value="&s=3&z=0"></option>
+                    </select>
+                    <input id="searchReset" type="button"  />
+                    <input id="searchBtn" type="button"  />
+                </div>
+                <div id="searchList" class="searchList"><ul id="searchListUl"></ul></div>
+            </div>
+
+        </div>
+    </div>
+    <script type="text/javascript" src="image.js"></script>
+
+</body>
+</html>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1025 - 0
public/Ueditor/dialogs/image/image.js


BIN
public/Ueditor/dialogs/image/images/alignicon.jpg


BIN
public/Ueditor/dialogs/image/images/bg.png


BIN
public/Ueditor/dialogs/image/images/icons.gif


BIN
public/Ueditor/dialogs/image/images/icons.png


BIN
public/Ueditor/dialogs/image/images/image.png


BIN
public/Ueditor/dialogs/image/images/progress.png


BIN
public/Ueditor/dialogs/image/images/success.gif


BIN
public/Ueditor/dialogs/image/images/success.png


+ 98 - 0
public/Ueditor/dialogs/insertframe/insertframe.html

@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+    <title></title>
+    <script type="text/javascript" src="../internal.js"></script>
+    <style type="text/css">
+        .warp {width: 320px;height: 153px;margin-left:5px;padding: 20px 0 0 15px;position: relative;}
+        #url {width: 290px; margin-bottom: 2px; margin-left: -6px; margin-left: -2px\9;*margin-left:0;_margin-left:0; }
+        .format span{display: inline-block; width: 58px;text-align: center; zoom:1;}
+        table td{padding:5px 0;}
+        #align{width: 65px;height: 23px;line-height: 22px;}
+    </style>
+</head>
+<body>
+<div class="warp">
+        <table width="300" cellpadding="0" cellspacing="0">
+            <tr>
+                <td colspan="2" class="format">
+                    <span><var id="lang_input_address"></var></span>
+                    <input style="width:200px" id="url" type="text" value=""/>
+                </td>
+            </tr>
+            <tr>
+                <td colspan="2" class="format"><span><var id="lang_input_width"></var></span><input style="width:200px" type="text" id="width"/> px</td>
+
+            </tr>
+            <tr>
+                <td colspan="2" class="format"><span><var id="lang_input_height"></var></span><input style="width:200px" type="text" id="height"/> px</td>
+            </tr>
+            <tr>
+                <td><span><var id="lang_input_isScroll"></var></span><input type="checkbox" id="scroll"/> </td>
+                <td><span><var id="lang_input_frameborder"></var></span><input type="checkbox" id="frameborder"/> </td>
+            </tr>
+
+            <tr>
+                <td colspan="2"><span><var id="lang_input_alignMode"></var></span>
+                    <select id="align">
+                        <option value=""></option>
+                        <option value="left"></option>
+                        <option value="right"></option>
+                    </select>
+                </td>
+            </tr>
+        </table>
+</div>
+<script type="text/javascript">
+    var iframe = editor._iframe;
+    if(iframe){
+        $G("url").value = iframe.getAttribute("src")||"";
+        $G("width").value = iframe.getAttribute("width")||iframe.style.width.replace("px","")||"";
+        $G("height").value = iframe.getAttribute("height") || iframe.style.height.replace("px","") ||"";
+        $G("scroll").checked = (iframe.getAttribute("scrolling") == "yes") ? true : false;
+        $G("frameborder").checked = (iframe.getAttribute("frameborder") == "1") ? true : false;
+        $G("align").value = iframe.align ? iframe.align : "";
+    }
+    function queding(){
+        var  url = $G("url").value.replace(/^\s*|\s*$/ig,""),
+                width = $G("width").value,
+                height = $G("height").value,
+                scroll = $G("scroll"),
+                frameborder = $G("frameborder"),
+                float = $G("align").value,
+                newIframe = editor.document.createElement("iframe"),
+                div;
+        if(!url){
+            alert(lang.enterAddress);
+            return false;
+        }
+        newIframe.setAttribute("src",/http:\/\/|https:\/\//ig.test(url) ? url : "http://"+url);
+        /^[1-9]+[.]?\d*$/g.test( width ) ? newIframe.setAttribute("width",width) : "";
+        /^[1-9]+[.]?\d*$/g.test( height ) ? newIframe.setAttribute("height",height) : "";
+        scroll.checked ?  newIframe.setAttribute("scrolling","yes") : newIframe.setAttribute("scrolling","no");
+        frameborder.checked ?  newIframe.setAttribute("frameborder","1",0) : newIframe.setAttribute("frameborder","0",0);
+        float ? newIframe.setAttribute("align",float) :  newIframe.setAttribute("align","");
+        if(iframe){
+            iframe.parentNode.insertBefore(newIframe,iframe);
+            domUtils.remove(iframe);
+        }else{
+            div = editor.document.createElement("div");
+            div.appendChild(newIframe);
+            editor.execCommand("inserthtml",div.innerHTML);
+        }
+        editor._iframe = null;
+        dialog.close();
+    }
+    dialog.onok = queding;
+    $G("url").onkeydown = function(evt){
+        evt = evt || event;
+        if(evt.keyCode == 13){
+            queding();
+        }
+    };
+    $focus($G( "url" ));
+
+</script>
+</body>
+</html>

+ 81 - 0
public/Ueditor/dialogs/internal.js

@@ -0,0 +1,81 @@
+(function () {
+    var parent = window.parent;
+    //dialog对象
+    dialog = parent.$EDITORUI[window.frameElement.id.replace( /_iframe$/, '' )];
+    //当前打开dialog的编辑器实例
+    editor = dialog.editor;
+
+    UE = parent.UE;
+
+    domUtils = UE.dom.domUtils;
+
+    utils = UE.utils;
+
+    browser = UE.browser;
+
+    ajax = UE.ajax;
+
+    $G = function ( id ) {
+        return document.getElementById( id )
+    };
+    //focus元素
+    $focus = function ( node ) {
+        setTimeout( function () {
+            if ( browser.ie ) {
+                var r = node.createTextRange();
+                r.collapse( false );
+                r.select();
+            } else {
+                node.focus()
+            }
+        }, 0 )
+    };
+    utils.loadFile(document,{
+        href:editor.options.themePath + editor.options.theme + "/dialogbase.css?cache="+Math.random(),
+        tag:"link",
+        type:"text/css",
+        rel:"stylesheet"
+    });
+    lang = editor.getLang(dialog.className.split( "-" )[2]);
+    if(lang){
+        domUtils.on(window,'load',function () {
+
+            var langImgPath = editor.options.langPath + editor.options.lang + "/images/";
+            //针对静态资源
+            for ( var i in lang["static"] ) {
+                var dom = $G( i );
+                if(!dom) continue;
+                var tagName = dom.tagName,
+                    content = lang["static"][i];
+                if(content.src){
+                    //clone
+                    content = utils.extend({},content,false);
+                    content.src = langImgPath + content.src;
+                }
+                if(content.style){
+                    content = utils.extend({},content,false);
+                    content.style = content.style.replace(/url\s*\(/g,"url(" + langImgPath)
+                }
+                switch ( tagName.toLowerCase() ) {
+                    case "var":
+                        dom.parentNode.replaceChild( document.createTextNode( content ), dom );
+                        break;
+                    case "select":
+                        var ops = dom.options;
+                        for ( var j = 0, oj; oj = ops[j]; ) {
+                            oj.innerHTML = content.options[j++];
+                        }
+                        for ( var p in content ) {
+                            p != "options" && dom.setAttribute( p, content[p] );
+                        }
+                        break;
+                    default :
+                        domUtils.setAttributes( dom, content);
+                }
+            }
+        } );
+    }
+
+
+})();
+

+ 126 - 0
public/Ueditor/dialogs/link/link.html

@@ -0,0 +1,126 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title></title>
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
+    <script type="text/javascript" src="../internal.js"></script>
+    <style type="text/css">
+        *{margin:0;padding:0;color: #838383;}
+        table{font-size: 12px;margin: 10px;line-height: 30px}
+        .txt{width:300px;height:21px;line-height:21px;border:1px solid #d7d7d7;}
+    </style>
+</head>
+<body>
+    <table>
+        <tr>
+            <td><label for="text"> <var id="lang_input_text"></var></label></td>
+            <td><input class="txt" id="text" type="text" disabled="true"/></td>
+        </tr>
+        <tr>
+            <td><label for="href"> <var id="lang_input_url"></var></label></td>
+            <td><input class="txt" id="href" type="text" /></td>
+        </tr>
+        <tr>
+            <td><label for="title"> <var id="lang_input_title"></var></label></td>
+            <td><input class="txt" id="title" type="text"/></td>
+        </tr>
+        <tr>
+             <td colspan="2">
+                 <label for="target"><var id="lang_input_target"></var></label>
+                 <input id="target" type="checkbox"/>
+             </td>
+        </tr>
+        <tr>
+            <td colspan="2" id="msg"></td>
+        </tr>
+    </table>
+<script type="text/javascript">
+    var range = editor.selection.getRange(),
+        link = range.collapsed ? editor.queryCommandValue( "link" ) : editor.selection.getStart(),
+        url,
+        text = $G('text'),
+        rangeLink = domUtils.findParentByTagName(range.getCommonAncestor(),'a',true),
+        orgText;
+    link = domUtils.findParentByTagName( link, "a", true );
+    if(link){
+        url = utils.html(link.getAttribute( '_href' ) || link.getAttribute( 'href', 2 ));
+
+        if(rangeLink === link && !link.getElementsByTagName('img').length){
+            text.removeAttribute('disabled');
+            orgText = text.value = link[browser.ie ? 'innerText':'textContent'];
+        }else{
+            text.setAttribute('disabled','true');
+            text.value = lang.validLink;
+        }
+
+    }else{
+        if(range.collapsed){
+            text.removeAttribute('disabled');
+            text.value = '';
+        }else{
+            text.setAttribute('disabled','true');
+            text.value = lang.validLink;
+        }
+
+    }
+    $G("title").value = url ? link.title : "";
+    $G("href").value = url ? url: '';
+    $G("target").checked = url && link.target == "_blank" ? true :  false;
+    $focus($G("href"));
+
+    function handleDialogOk(){
+        var href =$G('href').value.replace(/^\s+|\s+$/g, '');
+        if(href){
+            if(!hrefStartWith(href,["http","/","ftp://",'#'])) {
+                href  = "http://" + href;
+            }
+            var obj = {
+                'href' : href,
+                'target' : $G("target").checked ? "_blank" : '_self',
+                'title' : $G("title").value.replace(/^\s+|\s+$/g, ''),
+                '_href':href
+            };
+            //修改链接内容的情况太特殊了,所以先做到这里了
+            //todo:情况多的时候,做到command里
+            if(orgText && text.value != orgText){
+                link[browser.ie ? 'innerText' : 'textContent'] =  obj.textValue = text.value;
+                range.selectNode(link).select()
+            }
+            if(range.collapsed){
+                obj.textValue = text.value;
+            }
+            editor.execCommand('link',utils.clearEmptyAttrs(obj) );
+            dialog.close();
+        }
+    }
+    dialog.onok = handleDialogOk;
+    $G('href').onkeydown = $G('title').onkeydown = function(evt){
+        evt = evt || window.event;
+        if (evt.keyCode == 13) {
+            handleDialogOk();
+            return false;
+        }
+    };
+    $G('href').onblur = function(){
+        if(!hrefStartWith(this.value,["http","/","ftp://",'#'])){
+            $G("msg").innerHTML = "<span style='color: red'>"+lang.httpPrompt+"</span>";
+        }else{
+            $G("msg").innerHTML = "";
+        }
+    };
+
+    function hrefStartWith(href,arr){
+        href = href.replace(/^\s+|\s+$/g, '');
+        for(var i=0,ai;ai=arr[i++];){
+            if(href.indexOf(ai)==0){
+                return true;
+            }
+        }
+        return false;
+    }
+
+
+</script>
+</body>
+</html>

+ 135 - 0
public/Ueditor/dialogs/map/map.html

@@ -0,0 +1,135 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title></title>
+    <script type="text/javascript" src="../internal.js"></script>
+    <script type="text/javascript" src="http://api.map.baidu.com/api?v=1.1&services=true"></script>
+    <style type="text/css">
+        .content{width:530px; height: 350px;margin: 10px auto;}
+        .content table{width: 100%}
+        .content table td{vertical-align: middle;}
+        #city,#address{height:21px;background: #FFF;border:1px solid #d7d7d7; line-height: 21px;}
+        #city{width:60px}
+        #address{width:130px}
+        #is_dynamic_label span{vertical-align:middle;margin: 3px 0px 3px 3px;}
+        #is_dynamic_label input{vertical-align:middle;margin: 3px 3px 3px 50px;}
+    </style>
+</head>
+<body>
+<div class="content">
+    <table>
+        <tr>
+            <td><var id="lang_city"></var>:</td>
+            <td><input id="city" type="text" /></td>
+            <td><var id="lang_address"></var>:</td>
+            <td><input id="address" type="text" value="" /></td>
+            <td><a href="javascript:doSearch()" class="button"><var id="lang_search"></var></a></td>
+            <td><label id="is_dynamic_label" for="is_dynamic"><input id="is_dynamic" type="checkbox" name="is_dynamic" /><span><var id="lang_dynamicmap"></var></span></label></td>
+        </tr>
+    </table>
+    <div style="width:100%;height:340px;margin:5px auto;border:1px solid gray" id="container"></div>
+
+</div>
+<script type="text/javascript">
+    var map = new BMap.Map("container"),marker,point,styleStr;
+    map.enableScrollWheelZoom();
+    map.enableContinuousZoom();
+    function doSearch(){
+        if (!document.getElementById('city').value) {
+            alert(lang.cityMsg);
+            return;
+        }
+        var search = new BMap.LocalSearch(document.getElementById('city').value, {
+            onSearchComplete: function (results){
+                if (results && results.getNumPois()) {
+                    var points = [];
+                    for (var i=0; i<results.getCurrentNumPois(); i++) {
+                        points.push(results.getPoi(i).point);
+                    }
+                    if (points.length > 1) {
+                        map.setViewport(points);
+                    } else {
+                        map.centerAndZoom(points[0], 13);
+                    }
+                    point = map.getCenter();
+                    marker.setPoint(point);
+                } else {
+                    alert(lang.errorMsg);
+                }
+            }
+        });
+        search.search(document.getElementById('address').value || document.getElementById('city').value);
+    }
+    //获得参数
+    function getPars(str,par){
+        var reg = new RegExp(par+"=((\\d+|[.,])*)","g");
+        return reg.exec(str)[1];
+    }
+    function init(){
+        var mapNode = editor.selection.getRange().getClosedNode(),
+            isMapImg = mapNode && /api[.]map[.]baidu[.]com/ig.test(mapNode.getAttribute("src")),
+            isMapIframe = mapNode && domUtils.hasClass(mapNode, 'ueditor_baidumap');
+        if(isMapImg || isMapIframe){
+            var url, centerPos, markerPos;
+            if(isMapIframe) {
+                url = decodeURIComponent(mapNode.getAttribute("src"));
+                $G('is_dynamic').checked = true;
+                styleStr = mapNode.style.cssText;
+            } else {
+                url = mapNode.getAttribute("src");
+                styleStr = mapNode.style.cssText;
+            }
+
+            centerPos = getPars(url,"center").split(",");
+            markerPos = getPars(url, "markers").split(",");
+            point = new BMap.Point(Number(centerPos[0]),Number(centerPos[1]));
+            marker = new BMap.Marker(new BMap.Point(Number(markerPos[0]), Number(markerPos[1])));
+            map.addControl(new BMap.NavigationControl());
+            map.centerAndZoom(point, Number(getPars(url,"zoom")));
+        }else{
+            point = new BMap.Point(116.404, 39.915);    // 创建点坐标
+            marker = new BMap.Marker(point);
+            map.addControl(new BMap.NavigationControl());
+            map.centerAndZoom(point, 10);                     // 初始化地图,设置中心点坐标和地图级别。
+        }
+        marker.enableDragging();
+        map.addOverlay(marker);
+    }
+    init();
+    document.getElementById('address').onkeydown = function (evt){
+        evt = evt || event;
+        if (evt.keyCode == 13) {
+            doSearch();
+        }
+    };
+    dialog.onok = function (){
+        var center = map.getCenter();
+        var zoom = map.zoomLevel;
+        var size = map.getSize();
+        var mapWidth = size.width;
+        var mapHeight = size.height;
+        var point = marker.getPoint();
+
+        if($G('is_dynamic').checked) {
+            var URL = editor.options.UEDITOR_HOME_URL,
+                url = [URL + (/\/$/.test(URL) ? '':'/') + "dialogs/map/show.html" +
+                    '#center=' + center.lng + ',' + center.lat,
+                    '&zoom=' + zoom,
+                    '&width=' + mapWidth,
+                    '&height=' + mapHeight,
+                    '&markers=' + point.lng + ',' + point.lat,
+                    '&markerStyles=' + 'l,A'].join('');
+            editor.execCommand('inserthtml', '<iframe class="ueditor_baidumap" src="' + url + '"' + (styleStr ? ' style="' + styleStr + '"' :'') + ' frameborder="0" width="' + (mapWidth+4) + '" height="' + (mapHeight+4) + '"></iframe>');
+        } else {
+            var url = "http://api.map.baidu.com/staticimage?center=" + center.lng + ',' + center.lat +
+                    "&zoom=" + zoom + "&width=" + size.width + '&height=' + size.height + "&markers=" + point.lng + ',' + point.lat;
+            editor.execCommand('inserthtml', '<img width="'+ size.width +'"height="'+ size.height +'" src="' + url + '"' + (styleStr ? ' style="' + styleStr + '"' :'') + '/>');
+        }
+    };
+    document.getElementById("address").focus();
+</script>
+
+
+</body>
+</html>

+ 118 - 0
public/Ueditor/dialogs/map/show.html

@@ -0,0 +1,118 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+    <meta charset="utf-8"/>
+    <meta name="keywords" content="百度地图,百度地图API,百度地图自定义工具,百度地图所见即所得工具"/>
+    <meta name="description" content="百度地图API自定义地图,帮助用户在可视化操作下生成百度地图"/>
+    <title>百度地图API自定义地图</title>
+    <!--引用百度地图API-->
+    <style type="text/css">
+        html, body {
+            margin: 0;
+            padding: 0;
+            overflow: hidden;
+        }
+    </style>
+    <script type="text/javascript" src="http://api.map.baidu.com/api?key=&v=1.1&services=true"></script>
+</head>
+
+<body onload="initMap();">
+<!--百度地图容器-->
+<div style="width:697px;height:550px;border:#ccc solid 1px;" id="dituContent"></div>
+</body>
+<script type="text/javascript">
+    function getParam(name) {
+        return location.href.match(new RegExp('[?#&]' + name + '=([^?#&]+)', 'i')) ? RegExp.$1 : '';
+    }
+    var map, marker;
+    var centerParam = getParam('center');
+    var zoomParam = getParam('zoom');
+    var widthParam = getParam('width');
+    var heightParam = getParam('height');
+    var markersParam = getParam('markers');
+    var markerStylesParam = getParam('markerStyles');
+
+    //创建和初始化地图函数:
+    function initMap() {
+        // [FF]切换模式后报错
+        if (!window.BMap) {
+            return;
+        }
+        var dituContent = document.getElementById('dituContent');
+        dituContent.style.width = widthParam + 'px';
+        dituContent.style.height = heightParam + 'px';
+
+        createMap();//创建地图
+        setMapEvent();//设置地图事件
+        addMapControl();//向地图添加控件
+
+        // 创建标注
+        var markersArr = markersParam.split(',');
+        var point = new BMap.Point(markersArr[0], markersArr[1]);
+        marker = new BMap.Marker(point);
+        marker.enableDragging();
+        map.addOverlay(marker); // 将标注添加到地图中
+
+        if(parent.editor && parent.document.body.contentEditable=="true") { //在编辑状态下
+            setMapListener();//地图改变修改外层的iframe标签src属性
+        }
+    }
+
+    //创建地图函数:
+    function createMap() {
+        map = new BMap.Map("dituContent");//在百度地图容器中创建一个地图
+        var centerArr = centerParam.split(',');
+        var point = new BMap.Point(parseFloat(centerArr[0]), parseFloat(centerArr[1]));//定义一个中心点坐标
+        map.centerAndZoom(point, parseInt(zoomParam));//设定地图的中心点和坐标并将地图显示在地图容器中
+    }
+
+    //地图事件设置函数:
+    function setMapEvent() {
+        map.enableDragging();//启用地图拖拽事件,默认启用(可不写)
+        map.enableScrollWheelZoom();//启用地图滚轮放大缩小
+        map.enableDoubleClickZoom();//启用鼠标双击放大,默认启用(可不写)
+        map.enableKeyboard();//启用键盘上下左右键移动地图
+    }
+
+    //地图控件添加函数:
+    function addMapControl() {
+        //向地图中添加缩放控件
+        var ctrl_nav = new BMap.NavigationControl({anchor: BMAP_ANCHOR_TOP_LEFT, type: BMAP_NAVIGATION_CONTROL_LARGE});
+        map.addControl(ctrl_nav);
+        //向地图中添加缩略图控件
+        var ctrl_ove = new BMap.OverviewMapControl({anchor: BMAP_ANCHOR_BOTTOM_RIGHT, isOpen: 1});
+        map.addControl(ctrl_ove);
+        //向地图中添加比例尺控件
+        var ctrl_sca = new BMap.ScaleControl({anchor: BMAP_ANCHOR_BOTTOM_LEFT});
+        map.addControl(ctrl_sca);
+    }
+
+    function setMapListener() {
+        var editor = parent.editor, containerIframe,
+            iframes = parent.document.getElementsByTagName('iframe');
+        for (var key in iframes) {
+            if (iframes[key].contentWindow == window) {
+                containerIframe = iframes[key];
+                break;
+            }
+        }
+        if (containerIframe) {
+            map.addEventListener('moveend', mapListenerHandler);
+            map.addEventListener('zoomend', mapListenerHandler);
+            marker.addEventListener('dragend', mapListenerHandler);
+        }
+
+        function mapListenerHandler() {
+            var zoom = map.getZoom(),
+                center = map.getCenter(),
+                marker = window.marker.getPoint();
+            containerIframe.src = containerIframe.src.
+                replace(new RegExp('([?#&])center=([^?#&]+)', 'i'), '$1center=' + center.lng + ',' + center.lat).
+                replace(new RegExp('([?#&])markers=([^?#&]+)', 'i'), '$1markers=' + marker.lng + ',' + marker.lat).
+                replace(new RegExp('([?#&])zoom=([^?#&]+)', 'i'), '$1zoom=' + zoom);
+            editor.fireEvent('saveScene');
+        }
+    }
+</script>
+</html>

+ 30 - 0
public/Ueditor/dialogs/music/music.css

@@ -0,0 +1,30 @@
+.wrapper{margin: 5px 10px;}
+
+.searchBar{height:30px;padding:7px 0 3px;text-align:center;}
+.searchBtn{font-size:13px;height:24px;}
+
+.resultBar{width:460px;margin:5px auto;border: 1px solid #CCC;border-radius: 5px;box-shadow: 2px 2px 5px #D3D6DA;overflow: hidden;}
+
+.listPanel{overflow: hidden;}
+.panelon{display:block;}
+.paneloff{display:none}
+
+.page{width:220px;margin:20px auto;overflow: hidden;}
+.pageon{float:right;width:24px;line-height:24px;height:24px;margin-right: 5px;background: none;border: none;color: #000;font-weight: bold;text-align:center}
+.pageoff{float:right;width:24px;line-height:24px;height:24px;cursor:pointer;background-color: #fff;
+   border: 1px solid #E7ECF0;color: #2D64B3;margin-right: 5px;text-decoration: none;text-align:center;}
+
+.m-box{width:460px;}
+.m-m{float: left;line-height: 20px;height: 20px;}
+.m-h{height:24px;line-height:24px;padding-left: 46px;background-color:#FAFAFA;border-bottom: 1px solid #DAD8D8;font-weight: bold;font-size: 12px;color: #333;}
+.m-l{float:left;width:40px; }
+.m-t{float:left;width:140px;}
+.m-s{float:left;width:110px;}
+.m-z{float:left;width:100px;}
+.m-try-t{float: left;width: 60px;;}
+
+.m-try{float:left;width:20px;height:20px;background:url('http://static.tieba.baidu.com/tb/editor/images/try_music.gif') no-repeat ;}
+.m-trying{float:left;width:20px;height:20px;background:url('http://static.tieba.baidu.com/tb/editor/images/stop_music.gif') no-repeat ;}
+
+.loading{width:95px;height:7px;font-size:7px;margin:60px auto;background:url(http://static.tieba.baidu.com/tb/editor/images/loading.gif) no-repeat}
+.empty{width:300px;height:40px;padding:2px;margin:50px auto;line-height:40px; color:#006699;text-align:center;}

+ 32 - 0
public/Ueditor/dialogs/music/music.html

@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
+    <title>插入音乐</title>
+    <script type="text/javascript" src="../internal.js"></script>
+    <link rel="stylesheet" type="text/css" href="music.css">
+</head>
+<body>
+<div class="wrapper">
+    <div class="searchBar">
+        <input id="J_searchName" type="text"/>
+        <input type="button" class="searchBtn" id="J_searchBtn">
+    </div>
+    <div class="resultBar" id="J_resultBar">
+        <div class="loading" style="display:none"></div>
+        <div class="empty"><var id="lang_input_tips"></var></div>
+    </div>
+    <div id="J_preview"></div>
+</div>
+<script type="text/javascript" src="music.js"></script>
+<script type="text/javascript">
+    var music = new Music;
+    dialog.onok = function () {
+        music.exec();
+    };
+    dialog.oncancel = function () {
+        $G('J_preview').innerHTML = "";
+    };
+</script>
+</body>
+</html>

+ 192 - 0
public/Ueditor/dialogs/music/music.js

@@ -0,0 +1,192 @@
+function Music() {
+    this.init();
+}
+(function () {
+    var pages = [],
+        panels = [],
+        selectedItem = null;
+    Music.prototype = {
+        total:70,
+        pageSize:10,
+        dataUrl:"http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.common",
+        playerUrl:"http://box.baidu.com/widget/flash/bdspacesong.swf",
+
+        init:function () {
+            var me = this;
+            domUtils.on($G("J_searchName"), "keyup", function (event) {
+                var e = window.event || event;
+                if (e.keyCode == 13) {
+                    me.dosearch();
+                }
+            });
+            domUtils.on($G("J_searchBtn"), "click", function () {
+                me.dosearch();
+            });
+        },
+        callback:function (data) {
+            var me = this;
+            me.data = data.song_list;
+            setTimeout(function () {
+                $G('J_resultBar').innerHTML = me._renderTemplate(data.song_list);
+            }, 300);
+        },
+        dosearch:function () {
+            var me = this;
+            selectedItem = null;
+            var key = $G('J_searchName').value;
+            if (utils.trim(key) == "")return false;
+            key = encodeURIComponent(key);
+            me._sent(key);
+        },
+        doselect:function (i) {
+            var me = this;
+            if (typeof i == 'object') {
+                selectedItem = i;
+            } else if (typeof i == 'number') {
+                selectedItem = me.data[i];
+            }
+        },
+        onpageclick:function (id) {
+            var me = this;
+            for (var i = 0; i < pages.length; i++) {
+                $G(pages[i]).className = 'pageoff';
+                $G(panels[i]).className = 'paneloff';
+            }
+            $G('page' + id).className = 'pageon';
+            $G('panel' + id).className = 'panelon';
+        },
+        listenTest:function (elem) {
+            var me = this,
+                view = $G('J_preview'),
+                is_play_action = (elem.className == 'm-try'),
+                old_trying = me._getTryingElem();
+
+            if (old_trying) {
+                old_trying.className = 'm-try';
+                view.innerHTML = '';
+            }
+            if (is_play_action) {
+                elem.className = 'm-trying';
+                view.innerHTML = me._buildMusicHtml(me._getUrl(true));
+            }
+        },
+        _sent:function (param) {
+            var me = this;
+            $G('J_resultBar').innerHTML = '<div class="loading"></div>';
+
+            utils.loadFile(document, {
+                src:me.dataUrl + '&query=' + param + '&page_size=' + me.total + '&callback=music.callback&.r=' + Math.random(),
+                tag:"script",
+                type:"text/javascript",
+                defer:"defer"
+            });
+        },
+        _removeHtml:function (str) {
+            var reg = /<\s*\/?\s*[^>]*\s*>/gi;
+            return str.replace(reg, "");
+        },
+        _getUrl:function (isTryListen) {
+            var me = this;
+            var param = 'from=tiebasongwidget&url=&name=' + encodeURIComponent(me._removeHtml(selectedItem.title)) + '&artist='
+                + encodeURIComponent(me._removeHtml(selectedItem.author)) + '&extra='
+                + encodeURIComponent(me._removeHtml(selectedItem.album_title))
+                + '&autoPlay='+isTryListen+'' + '&loop=true';
+            return  me.playerUrl + "?" + param;
+        },
+        _getTryingElem:function () {
+            var s = $G('J_listPanel').getElementsByTagName('span');
+
+            for (var i = 0; i < s.length; i++) {
+                if (s[i].className == 'm-trying')
+                    return s[i];
+            }
+            return null;
+        },
+        _buildMusicHtml:function (playerUrl) {
+            var html = '<embed class="BDE_try_Music" allowfullscreen="false" pluginspage="http://www.macromedia.com/go/getflashplayer"';
+            html += ' src="' + playerUrl + '"';
+            html += ' width="1" height="1" style="position:absolute;left:-2000px;"';
+            html += ' type="application/x-shockwave-flash" wmode="transparent" play="true" loop="false"';
+            html += ' menu="false" allowscriptaccess="never" scale="noborder">';
+            return html;
+        },
+        _byteLength:function (str) {
+            return str.replace(/[^\u0000-\u007f]/g, "\u0061\u0061").length;
+        },
+        _getMaxText:function (s) {
+            var me = this;
+            s = me._removeHtml(s);
+            if (me._byteLength(s) > 12)
+                return s.substring(0, 5) + '...';
+            if (!s) s = "&nbsp;";
+            return s;
+        },
+        _rebuildData:function (data) {
+            var me = this,
+                newData = [],
+                d = me.pageSize,
+                itembox;
+            for (var i = 0; i < data.length; i++) {
+                if ((i + d) % d == 0) {
+                    itembox = [];
+                    newData.push(itembox)
+                }
+                itembox.push(data[i]);
+            }
+            return newData;
+        },
+        _renderTemplate:function (data) {
+            var me = this;
+            if (data.length == 0)return '<div class="empty">' + lang.emptyTxt + '</div>';
+            data = me._rebuildData(data);
+            var s = [], p = [], t = [];
+            s.push('<div id="J_listPanel" class="listPanel">');
+            p.push('<div class="page">');
+            for (var i = 0, tmpList; tmpList = data[i++];) {
+                panels.push('panel' + i);
+                pages.push('page' + i);
+                if (i == 1) {
+                    s.push('<div id="panel' + i + '" class="panelon">');
+                    if (data.length != 1) {
+                        t.push('<div id="page' + i + '" onclick="music.onpageclick(' + i + ')" class="pageon">' + (i ) + '</div>');
+                    }
+                } else {
+                    s.push('<div id="panel' + i + '" class="paneloff">');
+                    t.push('<div id="page' + i + '" onclick="music.onpageclick(' + i + ')" class="pageoff">' + (i ) + '</div>');
+                }
+                s.push('<div class="m-box">');
+                s.push('<div class="m-h"><span class="m-t">' + lang.chapter + '</span><span class="m-s">' + lang.singer
+                    + '</span><span class="m-z">' + lang.special + '</span><span class="m-try-t">' + lang.listenTest + '</span></div>');
+                for (var j = 0, tmpObj; tmpObj = tmpList[j++];) {
+                    s.push('<label for="radio-' + i + '-' + j + '" class="m-m">');
+                    s.push('<input type="radio" id="radio-' + i + '-' + j + '" name="musicId" class="m-l" onclick="music.doselect(' + (me.pageSize * (i-1) + (j-1)) + ')"/>');
+                    s.push('<span class="m-t">' + me._getMaxText(tmpObj.title) + '</span>');
+                    s.push('<span class="m-s">' + me._getMaxText(tmpObj.author) + '</span>');
+                    s.push('<span class="m-z">' + me._getMaxText(tmpObj.album_title) + '</span>');
+                    s.push('<span class="m-try" onclick="music.doselect(' + (me.pageSize * (i-1) + (j-1)) + ');music.listenTest(this)"></span>');
+                    s.push('</label>');
+                }
+                s.push('</div>');
+                s.push('</div>');
+            }
+            t.reverse();
+            p.push(t.join(''));
+            s.push('</div>');
+            p.push('</div>');
+            return s.join('') + p.join('');
+        },
+        exec:function () {
+            var me = this;
+            if (selectedItem == null)   return;
+            $G('J_preview').innerHTML = "";
+            editor.execCommand('music', {
+                url:me._getUrl(false),
+                width:400,
+                height:95
+            });
+        }
+    };
+})();
+
+
+

+ 40 - 0
public/Ueditor/dialogs/preview/preview.html

@@ -0,0 +1,40 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+    "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+    <head>
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
+        <style>
+            html,body{
+                height:100%;
+                width:100%;
+                padding:0;
+                margin:0;
+            }
+            #preview{
+                width:100%;
+                height:100%;
+                padding:0;
+                margin:0;
+            }
+            #preview *{font-family:sans-serif;font-size:16px;}
+        </style>
+        <script type="text/javascript" src="../internal.js"></script>
+        <script src="../../ueditor.parse.js"></script>
+        <title></title>
+    </head>
+    <body class="view">
+        <div id="preview" style="margin:8px">
+
+        </div>
+    </body>
+    <script>
+        document.getElementById('preview').innerHTML = editor.getContent();
+        uParse('#preview',{
+            rootPath : '../../',
+            chartContainerHeight:500
+        })
+        dialog.oncancel = function(){
+            document.getElementById('preview').innerHTML = '';
+        }
+    </script>
+</html>

BIN
public/Ueditor/dialogs/scrawl/images/addimg.png


BIN
public/Ueditor/dialogs/scrawl/images/brush.png


BIN
public/Ueditor/dialogs/scrawl/images/delimg.png


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio