hehaiqiang 1 年之前
父節點
當前提交
caeaca36d5
共有 100 個文件被更改,包括 7425 次插入0 次删除
  1. 21 0
      LICENSE
  2. 5 0
      babel.config.js
  3. 35 0
      build/index.js
  4. 7 0
      config/dev.env.js
  5. 40 0
      config/emoji.js
  6. 69 0
      config/index.js
  7. 4 0
      config/prod.env.js
  8. 24 0
      jest.config.js
  9. 9 0
      jsconfig.json
  10. 116 0
      mock/article.js
  11. 57 0
      mock/index.js
  12. 84 0
      mock/mock-server.js
  13. 51 0
      mock/remote-search.js
  14. 98 0
      mock/role/index.js
  15. 525 0
      mock/role/routes.js
  16. 84 0
      mock/user.js
  17. 124 0
      package.json
  18. 47 0
      patches/element-ui+2.13.2.patch
  19. 26 0
      plop-templates/component/index.hbs
  20. 55 0
      plop-templates/component/prompt.js
  21. 16 0
      plop-templates/store/index.hbs
  22. 62 0
      plop-templates/store/prompt.js
  23. 9 0
      plop-templates/utils.js
  24. 26 0
      plop-templates/view/index.hbs
  25. 55 0
      plop-templates/view/prompt.js
  26. 9 0
      plopfile.js
  27. 5 0
      postcss.config.js
  28. 40 0
      public/UEditor/dialogs/anchor/anchor.html
  29. 681 0
      public/UEditor/dialogs/attachment/attachment.css
  30. 60 0
      public/UEditor/dialogs/attachment/attachment.html
  31. 760 0
      public/UEditor/dialogs/attachment/attachment.js
  32. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_chm.gif
  33. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_default.png
  34. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_doc.gif
  35. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_exe.gif
  36. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_jpg.gif
  37. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_mp3.gif
  38. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_mv.gif
  39. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_pdf.gif
  40. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_ppt.gif
  41. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_psd.gif
  42. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_rar.gif
  43. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_txt.gif
  44. 二進制
      public/UEditor/dialogs/attachment/fileTypeImages/icon_xls.gif
  45. 二進制
      public/UEditor/dialogs/attachment/images/alignicon.gif
  46. 二進制
      public/UEditor/dialogs/attachment/images/alignicon.png
  47. 二進制
      public/UEditor/dialogs/attachment/images/bg.png
  48. 二進制
      public/UEditor/dialogs/attachment/images/file-icons.gif
  49. 二進制
      public/UEditor/dialogs/attachment/images/file-icons.png
  50. 二進制
      public/UEditor/dialogs/attachment/images/icons.gif
  51. 二進制
      public/UEditor/dialogs/attachment/images/icons.png
  52. 二進制
      public/UEditor/dialogs/attachment/images/image.png
  53. 二進制
      public/UEditor/dialogs/attachment/images/progress.png
  54. 二進制
      public/UEditor/dialogs/attachment/images/success.gif
  55. 二進制
      public/UEditor/dialogs/attachment/images/success.png
  56. 94 0
      public/UEditor/dialogs/background/background.css
  57. 56 0
      public/UEditor/dialogs/background/background.html
  58. 376 0
      public/UEditor/dialogs/background/background.js
  59. 二進制
      public/UEditor/dialogs/background/images/bg.png
  60. 二進制
      public/UEditor/dialogs/background/images/success.png
  61. 65 0
      public/UEditor/dialogs/charts/chart.config.js
  62. 165 0
      public/UEditor/dialogs/charts/charts.css
  63. 89 0
      public/UEditor/dialogs/charts/charts.html
  64. 519 0
      public/UEditor/dialogs/charts/charts.js
  65. 二進制
      public/UEditor/dialogs/charts/images/charts0.png
  66. 二進制
      public/UEditor/dialogs/charts/images/charts1.png
  67. 二進制
      public/UEditor/dialogs/charts/images/charts2.png
  68. 二進制
      public/UEditor/dialogs/charts/images/charts3.png
  69. 二進制
      public/UEditor/dialogs/charts/images/charts4.png
  70. 二進制
      public/UEditor/dialogs/charts/images/charts5.png
  71. 43 0
      public/UEditor/dialogs/emotion/emotion.css
  72. 54 0
      public/UEditor/dialogs/emotion/emotion.html
  73. 186 0
      public/UEditor/dialogs/emotion/emotion.js
  74. 二進制
      public/UEditor/dialogs/emotion/images/0.gif
  75. 二進制
      public/UEditor/dialogs/emotion/images/bface.gif
  76. 二進制
      public/UEditor/dialogs/emotion/images/cface.gif
  77. 二進制
      public/UEditor/dialogs/emotion/images/fface.gif
  78. 二進制
      public/UEditor/dialogs/emotion/images/jxface2.gif
  79. 二進制
      public/UEditor/dialogs/emotion/images/neweditor-tab-bg.png
  80. 二進制
      public/UEditor/dialogs/emotion/images/tface.gif
  81. 二進制
      public/UEditor/dialogs/emotion/images/wface.gif
  82. 二進制
      public/UEditor/dialogs/emotion/images/yface.gif
  83. 89 0
      public/UEditor/dialogs/gmap/gmap.html
  84. 7 0
      public/UEditor/dialogs/help/help.css
  85. 82 0
      public/UEditor/dialogs/help/help.html
  86. 56 0
      public/UEditor/dialogs/help/help.js
  87. 894 0
      public/UEditor/dialogs/image/image.css
  88. 120 0
      public/UEditor/dialogs/image/image.html
  89. 1148 0
      public/UEditor/dialogs/image/image.js
  90. 二進制
      public/UEditor/dialogs/image/images/alignicon.jpg
  91. 二進制
      public/UEditor/dialogs/image/images/bg.png
  92. 二進制
      public/UEditor/dialogs/image/images/icons.gif
  93. 二進制
      public/UEditor/dialogs/image/images/icons.png
  94. 二進制
      public/UEditor/dialogs/image/images/image.png
  95. 二進制
      public/UEditor/dialogs/image/images/progress.png
  96. 二進制
      public/UEditor/dialogs/image/images/success.gif
  97. 二進制
      public/UEditor/dialogs/image/images/success.png
  98. 98 0
      public/UEditor/dialogs/insertframe/insertframe.html
  99. 80 0
      public/UEditor/dialogs/internal.js
  100. 0 0
      public/UEditor/dialogs/link/link.html

+ 21 - 0
LICENSE

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

+ 5 - 0
babel.config.js

@@ -0,0 +1,5 @@
1
+module.exports = {
2
+  presets: [
3
+    '@vue/app'
4
+  ]
5
+}

+ 35 - 0
build/index.js

@@ -0,0 +1,35 @@
1
+const { run } = require('runjs')
2
+const chalk = require('chalk')
3
+const config = require('../vue.config.js')
4
+const rawArgv = process.argv.slice(2)
5
+const args = rawArgv.join(' ')
6
+
7
+if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
8
+  const report = rawArgv.includes('--report')
9
+
10
+  run(`vue-cli-service build ${args}`)
11
+
12
+  const port = 9526
13
+  const publicPath = config.publicPath
14
+
15
+  var connect = require('connect')
16
+  var serveStatic = require('serve-static')
17
+  const app = connect()
18
+
19
+  app.use(
20
+    publicPath,
21
+    serveStatic('./dist', {
22
+      index: ['index.html', '/']
23
+    })
24
+  )
25
+
26
+  app.listen(port, function () {
27
+    console.log(chalk.green(`> Preview at  http://localhost:${port}${publicPath}`))
28
+    if (report) {
29
+      console.log(chalk.green(`> Report at  http://localhost:${port}${publicPath}report.html`))
30
+    }
31
+
32
+  })
33
+} else {
34
+  run(`vue-cli-service build ${args}`)
35
+}

+ 7 - 0
config/dev.env.js

@@ -0,0 +1,7 @@
1
+'use strict';
2
+const merge = require('webpack-merge');
3
+const prodEnv = require('./prod.env');
4
+
5
+module.exports = merge(prodEnv, {
6
+	NODE_ENV: '"development"'
7
+});

+ 40 - 0
config/emoji.js

@@ -0,0 +1,40 @@
1
+module.exports = {
2
+	path: '../../../static/faces',
3
+	obj: {
4
+		'[):]': 'ee_1.png',
5
+		'[:D]': 'ee_2.png',
6
+		'[;)]': 'ee_3.png',
7
+		'[:-o]': 'ee_4.png',
8
+		'[:p]': 'ee_5.png',
9
+		'[(H)]': 'ee_6.png',
10
+		'[:@]': 'ee_7.png',
11
+		'[:s]': 'ee_8.png',
12
+		'[:$]': 'ee_9.png',
13
+		'[:(]': 'ee_10.png',
14
+		'[:\'(]': 'ee_11.png',
15
+		'[:|]': 'ee_18.png',
16
+		'[(a)]': 'ee_13.png',
17
+		'[8o|]': 'ee_14.png',
18
+		'[8-|]': 'ee_15.png',
19
+		'[+o(]': 'ee_16.png',
20
+		'[<o)]': 'ee_12.png',
21
+		'[|-)]': 'ee_17.png',
22
+		'[*-)]': 'ee_19.png',
23
+		'[:-#]': 'ee_20.png',
24
+		'[:-*]': 'ee_22.png',
25
+		'[^o)]': 'ee_21.png',
26
+		'[8-)]': 'ee_23.png',
27
+		'[(|)]': 'ee_24.png',
28
+		'[(u)]': 'ee_25.png',
29
+		'[(S)]': 'ee_26.png',
30
+		'[(*)]': 'ee_27.png',
31
+		'[(#)]': 'ee_28.png',
32
+		'[(R)]': 'ee_29.png',
33
+		'[({)]': 'ee_30.png',
34
+		'[(})]': 'ee_31.png',
35
+		'[(k)]': 'ee_32.png',
36
+		'[(F)]': 'ee_33.png',
37
+		'[(W)]': 'ee_34.png',
38
+		'[(D)]': 'ee_35.png'
39
+	}
40
+};

+ 69 - 0
config/index.js

@@ -0,0 +1,69 @@
1
+'use strict';
2
+// Template version: 1.3.1
3
+// see http://vuejs-templates.github.io/webpack for documentation.
4
+
5
+const path = require('path')
6
+
7
+module.exports = {
8
+	dev: {
9
+
10
+		// Paths
11
+		assetsSubDirectory: 'static',
12
+		assetsPublicPath: '/',
13
+		proxyTable: {},
14
+
15
+		// Various Dev Server settings
16
+		host: 'localhost', // can be overwritten by process.env.HOST
17
+		port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18
+		autoOpenBrowser: true,
19
+		errorOverlay: true,
20
+		notifyOnErrors: true,
21
+		poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22
+
23
+    
24
+		/**
25
+     * Source Maps
26
+     */
27
+
28
+		// https://webpack.js.org/configuration/devtool/#development
29
+		devtool: 'cheap-module-eval-source-map',
30
+
31
+		// If you have problems debugging vue-files in devtools,
32
+		// set this to false - it *may* help
33
+		// https://vue-loader.vuejs.org/en/options.html#cachebusting
34
+		cacheBusting: true,
35
+
36
+		cssSourceMap: true
37
+	},
38
+
39
+	build: {
40
+		// Template for index.html
41
+		index: path.resolve(__dirname, '../dist/index.html'),
42
+
43
+		// Paths
44
+		assetsRoot: path.resolve(__dirname, '../dist'),
45
+		assetsSubDirectory: 'static',
46
+		assetsPublicPath: '/',
47
+
48
+		/**
49
+     * Source Maps
50
+     */
51
+
52
+		productionSourceMap: true,
53
+		// https://webpack.js.org/configuration/devtool/#production
54
+		devtool: '#source-map',
55
+
56
+		// Gzip off by default as many popular static hosts such as
57
+		// Surge or Netlify already gzip all static assets for you.
58
+		// Before setting to `true`, make sure to:
59
+		// npm install --save-dev compression-webpack-plugin
60
+		productionGzip: false,
61
+		productionGzipExtensions: ['js', 'css'],
62
+
63
+		// Run the build command with an extra argument to
64
+		// View the bundle analyzer report after build finishes:
65
+		// `npm run build --report`
66
+		// Set to `true` or `false` to always turn it on or off
67
+		bundleAnalyzerReport: process.env.npm_config_report
68
+	}
69
+};

+ 4 - 0
config/prod.env.js

@@ -0,0 +1,4 @@
1
+'use strict';
2
+module.exports = {
3
+	NODE_ENV: '"production"'
4
+};

+ 24 - 0
jest.config.js

@@ -0,0 +1,24 @@
1
+module.exports = {
2
+  moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
3
+  transform: {
4
+    '^.+\\.vue$': 'vue-jest',
5
+    '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
6
+      'jest-transform-stub',
7
+    '^.+\\.jsx?$': 'babel-jest'
8
+  },
9
+  moduleNameMapper: {
10
+    '^@/(.*)$': '<rootDir>/src/$1'
11
+  },
12
+  snapshotSerializers: ['jest-serializer-vue'],
13
+  testMatch: [
14
+    '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
15
+  ],
16
+  collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
17
+  coverageDirectory: '<rootDir>/tests/unit/coverage',
18
+  // 'collectCoverage': true,
19
+  'coverageReporters': [
20
+    'lcov',
21
+    'text-summary'
22
+  ],
23
+  testURL: 'http://localhost/'
24
+}

+ 9 - 0
jsconfig.json

@@ -0,0 +1,9 @@
1
+{ 
2
+  "compilerOptions": {
3
+    "baseUrl": "./",
4
+    "paths": {
5
+        "@/*": ["src/*"]
6
+    }
7
+  },
8
+  "exclude": ["node_modules", "dist"]
9
+}

+ 116 - 0
mock/article.js

@@ -0,0 +1,116 @@
1
+import Mock from 'mockjs'
2
+
3
+const List = []
4
+const count = 100
5
+
6
+const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
7
+const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
8
+
9
+for (let i = 0; i < count; i++) {
10
+  List.push(Mock.mock({
11
+    id: '@increment',
12
+    timestamp: +Mock.Random.date('T'),
13
+    author: '@first',
14
+    reviewer: '@first',
15
+    title: '@title(5, 10)',
16
+    content_short: 'mock data',
17
+    content: baseContent,
18
+    forecast: '@float(0, 100, 2, 2)',
19
+    importance: '@integer(1, 3)',
20
+    'type|1': ['CN', 'US', 'JP', 'EU'],
21
+    'status|1': ['published', 'draft'],
22
+    display_time: '@datetime',
23
+    comment_disabled: true,
24
+    pageviews: '@integer(300, 5000)',
25
+    image_uri,
26
+    platforms: ['a-platform']
27
+  }))
28
+}
29
+
30
+export default [
31
+  {
32
+    url: '/vue-element-admin/article/list',
33
+    type: 'get',
34
+    response: config => {
35
+      const { importance, type, title, page = 1, limit = 20, sort } = config.query
36
+
37
+      let mockList = List.filter(item => {
38
+        if (importance && item.importance !== +importance) return false
39
+        if (type && item.type !== type) return false
40
+        if (title && item.title.indexOf(title) < 0) return false
41
+        return true
42
+      })
43
+
44
+      if (sort === '-id') {
45
+        mockList = mockList.reverse()
46
+      }
47
+
48
+      const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
49
+
50
+      return {
51
+        code: 20000,
52
+        data: {
53
+          total: mockList.length,
54
+          items: pageList
55
+        }
56
+      }
57
+    }
58
+  },
59
+
60
+  {
61
+    url: '/vue-element-admin/article/detail',
62
+    type: 'get',
63
+    response: config => {
64
+      const { id } = config.query
65
+      for (const article of List) {
66
+        if (article.id === +id) {
67
+          return {
68
+            code: 20000,
69
+            data: article
70
+          }
71
+        }
72
+      }
73
+    }
74
+  },
75
+
76
+  {
77
+    url: '/vue-element-admin/article/pv',
78
+    type: 'get',
79
+    response: _ => {
80
+      return {
81
+        code: 20000,
82
+        data: {
83
+          pvData: [
84
+            { key: 'PC', pv: 1024 },
85
+            { key: 'mobile', pv: 1024 },
86
+            { key: 'ios', pv: 1024 },
87
+            { key: 'android', pv: 1024 }
88
+          ]
89
+        }
90
+      }
91
+    }
92
+  },
93
+
94
+  {
95
+    url: '/vue-element-admin/article/create',
96
+    type: 'post',
97
+    response: _ => {
98
+      return {
99
+        code: 20000,
100
+        data: 'success'
101
+      }
102
+    }
103
+  },
104
+
105
+  {
106
+    url: '/vue-element-admin/article/update',
107
+    type: 'post',
108
+    response: _ => {
109
+      return {
110
+        code: 20000,
111
+        data: 'success'
112
+      }
113
+    }
114
+  }
115
+]
116
+

+ 57 - 0
mock/index.js

@@ -0,0 +1,57 @@
1
+import Mock from 'mockjs'
2
+import { param2Obj } from '../src/utils'
3
+
4
+import user from './user'
5
+import role from './role'
6
+import article from './article'
7
+import search from './remote-search'
8
+
9
+const mocks = [
10
+  ...user,
11
+  ...role,
12
+  ...article,
13
+  ...search
14
+]
15
+
16
+// for front mock
17
+// please use it cautiously, it will redefine XMLHttpRequest,
18
+// which will cause many of your third-party libraries to be invalidated(like progress event).
19
+export function mockXHR() {
20
+  // mock patch
21
+  // https://github.com/nuysoft/Mock/issues/300
22
+  Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
23
+  Mock.XHR.prototype.send = function() {
24
+    if (this.custom.xhr) {
25
+      this.custom.xhr.withCredentials = this.withCredentials || false
26
+
27
+      if (this.responseType) {
28
+        this.custom.xhr.responseType = this.responseType
29
+      }
30
+    }
31
+    this.proxy_send(...arguments)
32
+  }
33
+
34
+  function XHR2ExpressReqWrap(respond) {
35
+    return function(options) {
36
+      let result = null
37
+      if (respond instanceof Function) {
38
+        const { body, type, url } = options
39
+        // https://expressjs.com/en/4x/api.html#req
40
+        result = respond({
41
+          method: type,
42
+          body: JSON.parse(body),
43
+          query: param2Obj(url)
44
+        })
45
+      } else {
46
+        result = respond
47
+      }
48
+      return Mock.mock(result)
49
+    }
50
+  }
51
+
52
+  for (const i of mocks) {
53
+    Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
54
+  }
55
+}
56
+
57
+export default mocks

+ 84 - 0
mock/mock-server.js

@@ -0,0 +1,84 @@
1
+const chokidar = require('chokidar')
2
+const bodyParser = require('body-parser')
3
+const chalk = require('chalk')
4
+const path = require('path')
5
+const Mock = require('mockjs')
6
+
7
+const mockDir = path.join(process.cwd(), 'mock')
8
+
9
+function registerRoutes(app) {
10
+  let mockLastIndex
11
+  const { default: mocks } = require('./index.js')
12
+  const mocksForServer = mocks.map(route => {
13
+    return responseFake(route.url, route.type, route.response)
14
+  })
15
+  for (const mock of mocksForServer) {
16
+    app[mock.type](mock.url, mock.response)
17
+    mockLastIndex = app._router.stack.length
18
+  }
19
+  const mockRoutesLength = Object.keys(mocksForServer).length
20
+  return {
21
+    mockRoutesLength: mockRoutesLength,
22
+    mockStartIndex: mockLastIndex - mockRoutesLength
23
+  }
24
+}
25
+
26
+function unregisterRoutes() {
27
+  Object.keys(require.cache).forEach(i => {
28
+    if (i.includes(mockDir)) {
29
+      delete require.cache[require.resolve(i)]
30
+    }
31
+  })
32
+}
33
+
34
+// for mock server
35
+const responseFake = (url, type, respond) => {
36
+  return {
37
+    url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
38
+    type: type || 'get',
39
+    response(req, res) {
40
+      console.log('request invoke:' + req.path)
41
+      res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
42
+    }
43
+  }
44
+}
45
+
46
+module.exports = app => {
47
+  // es6 polyfill
48
+  require('@babel/register')
49
+
50
+  // parse app.body
51
+  // https://expressjs.com/en/4x/api.html#req.body
52
+  app.use(bodyParser.json())
53
+  app.use(bodyParser.urlencoded({
54
+    extended: true
55
+  }))
56
+
57
+  const mockRoutes = registerRoutes(app)
58
+  var mockRoutesLength = mockRoutes.mockRoutesLength
59
+  var mockStartIndex = mockRoutes.mockStartIndex
60
+
61
+  // watch files, hot reload mock server
62
+  chokidar.watch(mockDir, {
63
+    ignored: /mock-server/,
64
+    ignoreInitial: true
65
+  }).on('all', (event, path) => {
66
+    if (event === 'change' || event === 'add') {
67
+      try {
68
+        // remove mock routes stack
69
+        app._router.stack.splice(mockStartIndex, mockRoutesLength)
70
+
71
+        // clear routes cache
72
+        unregisterRoutes()
73
+
74
+        const mockRoutes = registerRoutes(app)
75
+        mockRoutesLength = mockRoutes.mockRoutesLength
76
+        mockStartIndex = mockRoutes.mockStartIndex
77
+
78
+        console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed  ${path}`))
79
+      } catch (error) {
80
+        console.log(chalk.redBright(error))
81
+      }
82
+    }
83
+  })
84
+}

+ 51 - 0
mock/remote-search.js

@@ -0,0 +1,51 @@
1
+import Mock from 'mockjs'
2
+
3
+const NameList = []
4
+const count = 100
5
+
6
+for (let i = 0; i < count; i++) {
7
+  NameList.push(Mock.mock({
8
+    name: '@first'
9
+  }))
10
+}
11
+NameList.push({ name: 'mock-Pan' })
12
+
13
+export default [
14
+  // username search
15
+  {
16
+    url: '/vue-element-admin/search/user',
17
+    type: 'get',
18
+    response: config => {
19
+      const { name } = config.query
20
+      const mockNameList = NameList.filter(item => {
21
+        const lowerCaseName = item.name.toLowerCase()
22
+        return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
23
+      })
24
+      return {
25
+        code: 20000,
26
+        data: { items: mockNameList }
27
+      }
28
+    }
29
+  },
30
+
31
+  // transaction list
32
+  {
33
+    url: '/vue-element-admin/transaction/list',
34
+    type: 'get',
35
+    response: _ => {
36
+      return {
37
+        code: 20000,
38
+        data: {
39
+          total: 20,
40
+          'items|20': [{
41
+            order_no: '@guid()',
42
+            timestamp: +Mock.Random.date('T'),
43
+            username: '@name()',
44
+            price: '@float(1000, 15000, 0, 2)',
45
+            'status|1': ['success', 'pending']
46
+          }]
47
+        }
48
+      }
49
+    }
50
+  }
51
+]

+ 98 - 0
mock/role/index.js

@@ -0,0 +1,98 @@
1
+import Mock from 'mockjs'
2
+import { deepClone } from '../../src/utils/index.js'
3
+import { asyncRoutes, constantRoutes } from './routes.js'
4
+
5
+const routes = deepClone([...constantRoutes, ...asyncRoutes])
6
+
7
+const roles = [
8
+  {
9
+    key: 'admin',
10
+    name: 'admin',
11
+    description: 'Super Administrator. Have access to view all pages.',
12
+    routes: routes
13
+  },
14
+  {
15
+    key: 'editor',
16
+    name: 'editor',
17
+    description: 'Normal Editor. Can see all pages except permission page',
18
+    routes: routes.filter(i => i.path !== '/permission')// just a mock
19
+  },
20
+  {
21
+    key: 'visitor',
22
+    name: 'visitor',
23
+    description: 'Just a visitor. Can only see the home page and the document page',
24
+    routes: [{
25
+      path: '',
26
+      redirect: 'dashboard',
27
+      children: [
28
+        {
29
+          path: 'dashboard',
30
+          name: 'Dashboard',
31
+          meta: { title: 'dashboard', icon: 'dashboard' }
32
+        }
33
+      ]
34
+    }]
35
+  }
36
+]
37
+
38
+export default [
39
+  // mock get all routes form server
40
+  {
41
+    url: '/vue-element-admin/routes',
42
+    type: 'get',
43
+    response: _ => {
44
+      return {
45
+        code: 20000,
46
+        data: routes
47
+      }
48
+    }
49
+  },
50
+
51
+  // mock get all roles form server
52
+  {
53
+    url: '/vue-element-admin/roles',
54
+    type: 'get',
55
+    response: _ => {
56
+      return {
57
+        code: 20000,
58
+        data: roles
59
+      }
60
+    }
61
+  },
62
+
63
+  // add role
64
+  {
65
+    url: '/vue-element-admin/role',
66
+    type: 'post',
67
+    response: {
68
+      code: 20000,
69
+      data: {
70
+        key: Mock.mock('@integer(300, 5000)')
71
+      }
72
+    }
73
+  },
74
+
75
+  // update role
76
+  {
77
+    url: '/vue-element-admin/role/[A-Za-z0-9]',
78
+    type: 'put',
79
+    response: {
80
+      code: 20000,
81
+      data: {
82
+        status: 'success'
83
+      }
84
+    }
85
+  },
86
+
87
+  // delete role
88
+  {
89
+    url: '/vue-element-admin/role/[A-Za-z0-9]',
90
+    type: 'delete',
91
+    response: {
92
+      code: 20000,
93
+      data: {
94
+        status: 'success'
95
+      }
96
+    }
97
+  }
98
+]

+ 525 - 0
mock/role/routes.js

@@ -0,0 +1,525 @@
1
+// Just a mock data
2
+
3
+export const constantRoutes = [
4
+  {
5
+    path: '/redirect',
6
+    component: 'layout/Layout',
7
+    hidden: true,
8
+    children: [
9
+      {
10
+        path: '/redirect/:path*',
11
+        component: 'views/redirect/index'
12
+      }
13
+    ]
14
+  },
15
+  {
16
+    path: '/login',
17
+    component: 'views/login/index',
18
+    hidden: true
19
+  },
20
+  {
21
+    path: '/auth-redirect',
22
+    component: 'views/login/auth-redirect',
23
+    hidden: true
24
+  },
25
+  {
26
+    path: '/404',
27
+    component: 'views/error-page/404',
28
+    hidden: true
29
+  },
30
+  {
31
+    path: '/401',
32
+    component: 'views/error-page/401',
33
+    hidden: true
34
+  },
35
+  {
36
+    path: '',
37
+    component: 'layout/Layout',
38
+    redirect: 'dashboard',
39
+    children: [
40
+      {
41
+        path: 'dashboard',
42
+        component: 'views/dashboard/index',
43
+        name: 'Dashboard',
44
+        meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
45
+      }
46
+    ]
47
+  },
48
+  {
49
+    path: '/documentation',
50
+    component: 'layout/Layout',
51
+    children: [
52
+      {
53
+        path: 'index',
54
+        component: 'views/documentation/index',
55
+        name: 'Documentation',
56
+        meta: { title: 'Documentation', icon: 'documentation', affix: true }
57
+      }
58
+    ]
59
+  },
60
+  {
61
+    path: '/guide',
62
+    component: 'layout/Layout',
63
+    redirect: '/guide/index',
64
+    children: [
65
+      {
66
+        path: 'index',
67
+        component: 'views/guide/index',
68
+        name: 'Guide',
69
+        meta: { title: 'Guide', icon: 'guide', noCache: true }
70
+      }
71
+    ]
72
+  }
73
+]
74
+
75
+export const asyncRoutes = [
76
+  {
77
+    path: '/permission',
78
+    component: 'layout/Layout',
79
+    redirect: '/permission/index',
80
+    alwaysShow: true,
81
+    meta: {
82
+      title: 'Permission',
83
+      icon: 'lock',
84
+      roles: ['admin', 'editor']
85
+    },
86
+    children: [
87
+      {
88
+        path: 'page',
89
+        component: 'views/permission/page',
90
+        name: 'PagePermission',
91
+        meta: {
92
+          title: 'Page Permission',
93
+          roles: ['admin']
94
+        }
95
+      },
96
+      {
97
+        path: 'directive',
98
+        component: 'views/permission/directive',
99
+        name: 'DirectivePermission',
100
+        meta: {
101
+          title: 'Directive Permission'
102
+        }
103
+      },
104
+      {
105
+        path: 'role',
106
+        component: 'views/permission/role',
107
+        name: 'RolePermission',
108
+        meta: {
109
+          title: 'Role Permission',
110
+          roles: ['admin']
111
+        }
112
+      }
113
+    ]
114
+  },
115
+
116
+  {
117
+    path: '/icon',
118
+    component: 'layout/Layout',
119
+    children: [
120
+      {
121
+        path: 'index',
122
+        component: 'views/icons/index',
123
+        name: 'Icons',
124
+        meta: { title: 'Icons', icon: 'icon', noCache: true }
125
+      }
126
+    ]
127
+  },
128
+
129
+  {
130
+    path: '/components',
131
+    component: 'layout/Layout',
132
+    redirect: 'noRedirect',
133
+    name: 'ComponentDemo',
134
+    meta: {
135
+      title: 'Components',
136
+      icon: 'component'
137
+    },
138
+    children: [
139
+      {
140
+        path: 'tinymce',
141
+        component: 'views/components-demo/tinymce',
142
+        name: 'TinymceDemo',
143
+        meta: { title: 'Tinymce' }
144
+      },
145
+      {
146
+        path: 'markdown',
147
+        component: 'views/components-demo/markdown',
148
+        name: 'MarkdownDemo',
149
+        meta: { title: 'Markdown' }
150
+      },
151
+      {
152
+        path: 'json-editor',
153
+        component: 'views/components-demo/json-editor',
154
+        name: 'JsonEditorDemo',
155
+        meta: { title: 'Json Editor' }
156
+      },
157
+      {
158
+        path: 'split-pane',
159
+        component: 'views/components-demo/split-pane',
160
+        name: 'SplitpaneDemo',
161
+        meta: { title: 'SplitPane' }
162
+      },
163
+      {
164
+        path: 'avatar-upload',
165
+        component: 'views/components-demo/avatar-upload',
166
+        name: 'AvatarUploadDemo',
167
+        meta: { title: 'Avatar Upload' }
168
+      },
169
+      {
170
+        path: 'dropzone',
171
+        component: 'views/components-demo/dropzone',
172
+        name: 'DropzoneDemo',
173
+        meta: { title: 'Dropzone' }
174
+      },
175
+      {
176
+        path: 'sticky',
177
+        component: 'views/components-demo/sticky',
178
+        name: 'StickyDemo',
179
+        meta: { title: 'Sticky' }
180
+      },
181
+      {
182
+        path: 'count-to',
183
+        component: 'views/components-demo/count-to',
184
+        name: 'CountToDemo',
185
+        meta: { title: 'Count To' }
186
+      },
187
+      {
188
+        path: 'mixin',
189
+        component: 'views/components-demo/mixin',
190
+        name: 'ComponentMixinDemo',
191
+        meta: { title: 'componentMixin' }
192
+      },
193
+      {
194
+        path: 'back-to-top',
195
+        component: 'views/components-demo/back-to-top',
196
+        name: 'BackToTopDemo',
197
+        meta: { title: 'Back To Top' }
198
+      },
199
+      {
200
+        path: 'drag-dialog',
201
+        component: 'views/components-demo/drag-dialog',
202
+        name: 'DragDialogDemo',
203
+        meta: { title: 'Drag Dialog' }
204
+      },
205
+      {
206
+        path: 'drag-select',
207
+        component: 'views/components-demo/drag-select',
208
+        name: 'DragSelectDemo',
209
+        meta: { title: 'Drag Select' }
210
+      },
211
+      {
212
+        path: 'dnd-list',
213
+        component: 'views/components-demo/dnd-list',
214
+        name: 'DndListDemo',
215
+        meta: { title: 'Dnd List' }
216
+      },
217
+      {
218
+        path: 'drag-kanban',
219
+        component: 'views/components-demo/drag-kanban',
220
+        name: 'DragKanbanDemo',
221
+        meta: { title: 'Drag Kanban' }
222
+      }
223
+    ]
224
+  },
225
+  {
226
+    path: '/charts',
227
+    component: 'layout/Layout',
228
+    redirect: 'noRedirect',
229
+    name: 'Charts',
230
+    meta: {
231
+      title: 'Charts',
232
+      icon: 'chart'
233
+    },
234
+    children: [
235
+      {
236
+        path: 'keyboard',
237
+        component: 'views/charts/keyboard',
238
+        name: 'KeyboardChart',
239
+        meta: { title: 'Keyboard Chart', noCache: true }
240
+      },
241
+      {
242
+        path: 'line',
243
+        component: 'views/charts/line',
244
+        name: 'LineChart',
245
+        meta: { title: 'Line Chart', noCache: true }
246
+      },
247
+      {
248
+        path: 'mixchart',
249
+        component: 'views/charts/mixChart',
250
+        name: 'MixChart',
251
+        meta: { title: 'Mix Chart', noCache: true }
252
+      }
253
+    ]
254
+  },
255
+  {
256
+    path: '/nested',
257
+    component: 'layout/Layout',
258
+    redirect: '/nested/menu1/menu1-1',
259
+    name: 'Nested',
260
+    meta: {
261
+      title: 'Nested',
262
+      icon: 'nested'
263
+    },
264
+    children: [
265
+      {
266
+        path: 'menu1',
267
+        component: 'views/nested/menu1/index',
268
+        name: 'Menu1',
269
+        meta: { title: 'Menu1' },
270
+        redirect: '/nested/menu1/menu1-1',
271
+        children: [
272
+          {
273
+            path: 'menu1-1',
274
+            component: 'views/nested/menu1/menu1-1',
275
+            name: 'Menu1-1',
276
+            meta: { title: 'Menu1-1' }
277
+          },
278
+          {
279
+            path: 'menu1-2',
280
+            component: 'views/nested/menu1/menu1-2',
281
+            name: 'Menu1-2',
282
+            redirect: '/nested/menu1/menu1-2/menu1-2-1',
283
+            meta: { title: 'Menu1-2' },
284
+            children: [
285
+              {
286
+                path: 'menu1-2-1',
287
+                component: 'views/nested/menu1/menu1-2/menu1-2-1',
288
+                name: 'Menu1-2-1',
289
+                meta: { title: 'Menu1-2-1' }
290
+              },
291
+              {
292
+                path: 'menu1-2-2',
293
+                component: 'views/nested/menu1/menu1-2/menu1-2-2',
294
+                name: 'Menu1-2-2',
295
+                meta: { title: 'Menu1-2-2' }
296
+              }
297
+            ]
298
+          },
299
+          {
300
+            path: 'menu1-3',
301
+            component: 'views/nested/menu1/menu1-3',
302
+            name: 'Menu1-3',
303
+            meta: { title: 'Menu1-3' }
304
+          }
305
+        ]
306
+      },
307
+      {
308
+        path: 'menu2',
309
+        name: 'Menu2',
310
+        component: 'views/nested/menu2/index',
311
+        meta: { title: 'Menu2' }
312
+      }
313
+    ]
314
+  },
315
+
316
+  {
317
+    path: '/example',
318
+    component: 'layout/Layout',
319
+    redirect: '/example/list',
320
+    name: 'Example',
321
+    meta: {
322
+      title: 'Example',
323
+      icon: 'example'
324
+    },
325
+    children: [
326
+      {
327
+        path: 'create',
328
+        component: 'views/example/create',
329
+        name: 'CreateArticle',
330
+        meta: { title: 'Create Article', icon: 'edit' }
331
+      },
332
+      {
333
+        path: 'edit/:id(\\d+)',
334
+        component: 'views/example/edit',
335
+        name: 'EditArticle',
336
+        meta: { title: 'Edit Article', noCache: true },
337
+        hidden: true
338
+      },
339
+      {
340
+        path: 'list',
341
+        component: 'views/example/list',
342
+        name: 'ArticleList',
343
+        meta: { title: 'Article List', icon: 'list' }
344
+      }
345
+    ]
346
+  },
347
+
348
+  {
349
+    path: '/tab',
350
+    component: 'layout/Layout',
351
+    children: [
352
+      {
353
+        path: 'index',
354
+        component: 'views/tab/index',
355
+        name: 'Tab',
356
+        meta: { title: 'Tab', icon: 'tab' }
357
+      }
358
+    ]
359
+  },
360
+
361
+  {
362
+    path: '/error',
363
+    component: 'layout/Layout',
364
+    redirect: 'noRedirect',
365
+    name: 'ErrorPages',
366
+    meta: {
367
+      title: 'Error Pages',
368
+      icon: '404'
369
+    },
370
+    children: [
371
+      {
372
+        path: '401',
373
+        component: 'views/error-page/401',
374
+        name: 'Page401',
375
+        meta: { title: 'Page 401', noCache: true }
376
+      },
377
+      {
378
+        path: '404',
379
+        component: 'views/error-page/404',
380
+        name: 'Page404',
381
+        meta: { title: 'Page 404', noCache: true }
382
+      }
383
+    ]
384
+  },
385
+
386
+  {
387
+    path: '/error-log',
388
+    component: 'layout/Layout',
389
+    redirect: 'noRedirect',
390
+    children: [
391
+      {
392
+        path: 'log',
393
+        component: 'views/error-log/index',
394
+        name: 'ErrorLog',
395
+        meta: { title: 'Error Log', icon: 'bug' }
396
+      }
397
+    ]
398
+  },
399
+
400
+  {
401
+    path: '/excel',
402
+    component: 'layout/Layout',
403
+    redirect: '/excel/export-excel',
404
+    name: 'Excel',
405
+    meta: {
406
+      title: 'Excel',
407
+      icon: 'excel'
408
+    },
409
+    children: [
410
+      {
411
+        path: 'export-excel',
412
+        component: 'views/excel/export-excel',
413
+        name: 'ExportExcel',
414
+        meta: { title: 'Export Excel' }
415
+      },
416
+      {
417
+        path: 'export-selected-excel',
418
+        component: 'views/excel/select-excel',
419
+        name: 'SelectExcel',
420
+        meta: { title: 'Select Excel' }
421
+      },
422
+      {
423
+        path: 'export-merge-header',
424
+        component: 'views/excel/merge-header',
425
+        name: 'MergeHeader',
426
+        meta: { title: 'Merge Header' }
427
+      },
428
+      {
429
+        path: 'upload-excel',
430
+        component: 'views/excel/upload-excel',
431
+        name: 'UploadExcel',
432
+        meta: { title: 'Upload Excel' }
433
+      }
434
+    ]
435
+  },
436
+
437
+  {
438
+    path: '/zip',
439
+    component: 'layout/Layout',
440
+    redirect: '/zip/download',
441
+    alwaysShow: true,
442
+    meta: { title: 'Zip', icon: 'zip' },
443
+    children: [
444
+      {
445
+        path: 'download',
446
+        component: 'views/zip/index',
447
+        name: 'ExportZip',
448
+        meta: { title: 'Export Zip' }
449
+      }
450
+    ]
451
+  },
452
+
453
+  {
454
+    path: '/pdf',
455
+    component: 'layout/Layout',
456
+    redirect: '/pdf/index',
457
+    children: [
458
+      {
459
+        path: 'index',
460
+        component: 'views/pdf/index',
461
+        name: 'PDF',
462
+        meta: { title: 'PDF', icon: 'pdf' }
463
+      }
464
+    ]
465
+  },
466
+  {
467
+    path: '/pdf/download',
468
+    component: 'views/pdf/download',
469
+    hidden: true
470
+  },
471
+
472
+  {
473
+    path: '/theme',
474
+    component: 'layout/Layout',
475
+    redirect: 'noRedirect',
476
+    children: [
477
+      {
478
+        path: 'index',
479
+        component: 'views/theme/index',
480
+        name: 'Theme',
481
+        meta: { title: 'Theme', icon: 'theme' }
482
+      }
483
+    ]
484
+  },
485
+
486
+  {
487
+    path: '/clipboard',
488
+    component: 'layout/Layout',
489
+    redirect: 'noRedirect',
490
+    children: [
491
+      {
492
+        path: 'index',
493
+        component: 'views/clipboard/index',
494
+        name: 'ClipboardDemo',
495
+        meta: { title: 'Clipboard Demo', icon: 'clipboard' }
496
+      }
497
+    ]
498
+  },
499
+
500
+  {
501
+    path: '/i18n',
502
+    component: 'layout/Layout',
503
+    children: [
504
+      {
505
+        path: 'index',
506
+        component: 'views/i18n-demo/index',
507
+        name: 'I18n',
508
+        meta: { title: 'I18n', icon: 'international' }
509
+      }
510
+    ]
511
+  },
512
+
513
+  {
514
+    path: 'external-link',
515
+    component: 'layout/Layout',
516
+    children: [
517
+      {
518
+        path: 'https://github.com/PanJiaChen/vue-element-admin',
519
+        meta: { title: 'External Link', icon: 'link' }
520
+      }
521
+    ]
522
+  },
523
+
524
+  { path: '*', redirect: '/404', hidden: true }
525
+]

+ 84 - 0
mock/user.js

@@ -0,0 +1,84 @@
1
+
2
+const tokens = {
3
+  admin: {
4
+    token: 'admin-token'
5
+  },
6
+  editor: {
7
+    token: 'editor-token'
8
+  }
9
+}
10
+
11
+const users = {
12
+  'admin-token': {
13
+    roles: ['admin'],
14
+    introduction: 'I am a super administrator',
15
+    avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
16
+    name: 'Super Admin'
17
+  },
18
+  'editor-token': {
19
+    roles: ['editor'],
20
+    introduction: 'I am an editor',
21
+    avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
22
+    name: 'Normal Editor'
23
+  }
24
+}
25
+
26
+export default [
27
+  // user login
28
+  {
29
+    url: '/vue-element-admin/user/login',
30
+    type: 'post',
31
+    response: config => {
32
+      const { username } = config.body
33
+      const token = tokens[username]
34
+
35
+      // mock error
36
+      if (!token) {
37
+        return {
38
+          code: 60204,
39
+          message: 'Account and password are incorrect.'
40
+        }
41
+      }
42
+
43
+      return {
44
+        code: 20000,
45
+        data: token
46
+      }
47
+    }
48
+  },
49
+
50
+  // get user info
51
+  {
52
+    url: '/vue-element-admin/user/info\.*',
53
+    type: 'get',
54
+    response: config => {
55
+      const { token } = config.query
56
+      const info = users[token]
57
+
58
+      // mock error
59
+      if (!info) {
60
+        return {
61
+          code: 50008,
62
+          message: 'Login failed, unable to get user details.'
63
+        }
64
+      }
65
+
66
+      return {
67
+        code: 20000,
68
+        data: info
69
+      }
70
+    }
71
+  },
72
+
73
+  // user logout
74
+  {
75
+    url: '/vue-element-admin/user/logout',
76
+    type: 'post',
77
+    response: _ => {
78
+      return {
79
+        code: 20000,
80
+        data: 'success'
81
+      }
82
+    }
83
+  }
84
+]

+ 124 - 0
package.json

@@ -0,0 +1,124 @@
1
+{
2
+  "name": "vue-element-admin",
3
+  "version": "4.2.1",
4
+  "description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
5
+  "author": "Pan <panfree23@gmail.com>",
6
+  "license": "MIT",
7
+  "scripts": {
8
+    "dev": "vue-cli-service serve",
9
+    "build:prod": "vue-cli-service build",
10
+    "build:stage": "vue-cli-service build --mode staging",
11
+    "preview": "node build/index.js --preview",
12
+    "lint": "eslint --ext .js,.vue src",
13
+    "test:unit": "jest --clearCache && vue-cli-service test:unit",
14
+    "test:ci": "npm run lint && npm run test:unit",
15
+    "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
16
+    "new": "plop",
17
+    "postinstall": "patch-package"
18
+  },
19
+  "bin": "npm run postinstall",
20
+  "lint-staged": {
21
+    "src/**/*.{js,vue}": [
22
+      "eslint --fix",
23
+      "git add"
24
+    ]
25
+  },
26
+  "keywords": [
27
+    "vue",
28
+    "admin",
29
+    "dashboard",
30
+    "element-ui",
31
+    "boilerplate",
32
+    "admin-template",
33
+    "management-system"
34
+  ],
35
+  "repository": {
36
+    "type": "git",
37
+    "url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
38
+  },
39
+  "bugs": {
40
+    "url": "https://github.com/PanJiaChen/vue-element-admin/issues"
41
+  },
42
+  "dependencies": {
43
+    "@form-create/element-ui": "^1.0.17",
44
+    "af-table-column": "^1.0.3",
45
+    "ant-design-vue": "^1.7.8",
46
+    "axios": "0.18.1",
47
+    "clipboard": "2.0.4",
48
+    "codemirror": "5.45.0",
49
+    "driver.js": "0.9.5",
50
+    "dropzone": "5.5.1",
51
+    "easemob-emedia": "^2.1.3",
52
+    "easemob-webrtc": "^3.2.2",
53
+    "echarts": "4.2.1",
54
+    "element-ui": "2.13.2",
55
+    "file-saver": "2.0.1",
56
+    "fuse.js": "3.4.4",
57
+    "js-cookie": "2.2.0",
58
+    "jsonlint": "1.6.3",
59
+    "jszip": "^3.10.1",
60
+    "node-sass": "^6.0.0",
61
+    "normalize.css": "7.0.0",
62
+    "nprogress": "0.2.0",
63
+    "path-to-regexp": "2.4.0",
64
+    "screenfull": "4.2.0",
65
+    "script-loader": "0.7.2",
66
+    "showdown": "1.9.0",
67
+    "sortablejs": "1.8.4",
68
+    "vant": "^2.12.37",
69
+    "view-design": "^4.3.2",
70
+    "vue": "2.6.10",
71
+    "vue-awesome-swiper": "^3.1.3",
72
+    "vue-count-to": "1.0.13",
73
+    "vue-router": "3.0.2",
74
+    "vue-splitpane": "1.0.4",
75
+    "vue-ueditor-wrap": "^2.4.1",
76
+    "vuedraggable": "2.20.0",
77
+    "vuex": "3.1.0",
78
+    "xlsx": "0.14.1"
79
+  },
80
+  "devDependencies": {
81
+    "@babel/core": "7.4.0",
82
+    "@babel/register": "7.0.0",
83
+    "@vue/cli-plugin-babel": "3.5.3",
84
+    "@vue/cli-plugin-eslint": "^3.9.1",
85
+    "@vue/cli-plugin-unit-jest": "3.5.3",
86
+    "@vue/cli-service": "3.5.3",
87
+    "@vue/test-utils": "1.0.0-beta.29",
88
+    "autoprefixer": "^9.5.1",
89
+    "babel-core": "7.0.0-bridge.0",
90
+    "babel-eslint": "10.0.1",
91
+    "babel-jest": "23.6.0",
92
+    "chalk": "2.4.2",
93
+    "chokidar": "2.1.5",
94
+    "connect": "3.6.6",
95
+    "easemob-websdk": "^4.7.0",
96
+    "eslint": "5.15.3",
97
+    "eslint-plugin-vue": "^5.2.2",
98
+    "html-webpack-plugin": "^4.0.0",
99
+    "husky": "1.3.1",
100
+    "less": "^3.10.3",
101
+    "less-loader": "^5.0.0",
102
+    "lint-staged": "8.1.5",
103
+    "mockjs": "1.0.1-beta3",
104
+    "patch-package": "^6.2.2",
105
+    "plop": "2.3.0",
106
+    "runjs": "^4.3.2",
107
+    "sass-loader": "^10.4.1",
108
+    "script-ext-html-webpack-plugin": "^2.1.5",
109
+    "serve-static": "^1.13.2",
110
+    "svg-sprite-loader": "4.1.3",
111
+    "svgo": "1.2.0",
112
+    "vue-lazyload": "^1.3.3",
113
+    "vue-template-compiler": "2.6.10",
114
+    "webpack": "^4.47.0"
115
+  },
116
+  "engines": {
117
+    "node": ">=16",
118
+    "npm": ">= 3.0.0"
119
+  },
120
+  "browserslist": [
121
+    "> 1%",
122
+    "last 2 versions"
123
+  ]
124
+}

+ 47 - 0
patches/element-ui+2.13.2.patch

@@ -0,0 +1,47 @@
1
+diff --git a/node_modules/element-ui/lib/cascader-panel.js b/node_modules/element-ui/lib/cascader-panel.js
2
+index 0f3f827..aba337b 100644
3
+--- a/node_modules/element-ui/lib/cascader-panel.js
4
++++ b/node_modules/element-ui/lib/cascader-panel.js
5
+@@ -1050,7 +1050,7 @@ var store_Store = function () {
6
+   };
7
+ 
8
+   Store.prototype.getNodeByValue = function getNodeByValue(value) {
9
+-    if (value) {
10
++    if (value || value === 0) {
11
+       var nodes = this.getFlattedNodes(false, !this.config.lazy).filter(function (node) {
12
+         return Object(util_["valueEquals"])(node.path, value) || node.value === value;
13
+       });
14
+diff --git a/node_modules/element-ui/lib/cascader.js b/node_modules/element-ui/lib/cascader.js
15
+index ee4bc3d..91242a0 100644
16
+--- a/node_modules/element-ui/lib/cascader.js
17
++++ b/node_modules/element-ui/lib/cascader.js
18
+@@ -1039,7 +1039,7 @@ var InputSizeMap = {
19
+       this.inputInitialHeight = input.$el.offsetHeight || InputSizeMap[this.realSize] || 40;
20
+     }
21
+ 
22
+-    if (!Object(util_["isEmpty"])(this.value)) {
23
++    if (this.value === 0 || !Object(util_["isEmpty"])(this.value)) {
24
+       this.computePresentContent();
25
+     }
26
+ 
27
+@@ -1189,7 +1189,7 @@ var InputSizeMap = {
28
+       var checkedValue = this.checkedValue,
29
+           config = this.config;
30
+ 
31
+-      if (!Object(util_["isEmpty"])(checkedValue)) {
32
++      if (checkedValue === 0 || !Object(util_["isEmpty"])(checkedValue)) {
33
+         var node = this.panel.getNodeByValue(checkedValue);
34
+         if (node && (config.checkStrictly || node.isLeaf)) {
35
+           this.presentText = node.getText(this.showAllLevels, this.separator);
36
+diff --git a/node_modules/element-ui/packages/.DS_Store b/node_modules/element-ui/packages/.DS_Store
37
+deleted file mode 100644
38
+index 1c1f7f4..0000000
39
+Binary files a/node_modules/element-ui/packages/.DS_Store and /dev/null differ
40
+diff --git a/node_modules/element-ui/packages/theme-chalk/src/.DS_Store b/node_modules/element-ui/packages/theme-chalk/src/.DS_Store
41
+deleted file mode 100644
42
+index 94b4cf9..0000000
43
+Binary files a/node_modules/element-ui/packages/theme-chalk/src/.DS_Store and /dev/null differ
44
+diff --git a/node_modules/element-ui/packages/theme-chalk/src/fonts/.DS_Store b/node_modules/element-ui/packages/theme-chalk/src/fonts/.DS_Store
45
+deleted file mode 100644
46
+index 5008ddf..0000000
47
+Binary files a/node_modules/element-ui/packages/theme-chalk/src/fonts/.DS_Store and /dev/null differ

+ 26 - 0
plop-templates/component/index.hbs

@@ -0,0 +1,26 @@
1
+{{#if template}}
2
+<template>
3
+  <div />
4
+</template>
5
+{{/if}}
6
+
7
+{{#if script}}
8
+<script>
9
+export default {
10
+  name: '{{ properCase name }}',
11
+  props: {},
12
+  data() {
13
+    return {}
14
+  },
15
+  created() {},
16
+  mounted() {},
17
+  methods: {}
18
+}
19
+</script>
20
+{{/if}}
21
+
22
+{{#if style}}
23
+<style lang="scss" scoped>
24
+
25
+</style>
26
+{{/if}}

+ 55 - 0
plop-templates/component/prompt.js

@@ -0,0 +1,55 @@
1
+const { notEmpty } = require('../utils.js')
2
+
3
+module.exports = {
4
+  description: 'generate vue component',
5
+  prompts: [{
6
+    type: 'input',
7
+    name: 'name',
8
+    message: 'component name please',
9
+    validate: notEmpty('name')
10
+  },
11
+  {
12
+    type: 'checkbox',
13
+    name: 'blocks',
14
+    message: 'Blocks:',
15
+    choices: [{
16
+      name: '<template>',
17
+      value: 'template',
18
+      checked: true
19
+    },
20
+    {
21
+      name: '<script>',
22
+      value: 'script',
23
+      checked: true
24
+    },
25
+    {
26
+      name: 'style',
27
+      value: 'style',
28
+      checked: true
29
+    }
30
+    ],
31
+    validate(value) {
32
+      if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
33
+        return 'Components require at least a <script> or <template> tag.'
34
+      }
35
+      return true
36
+    }
37
+  }
38
+  ],
39
+  actions: data => {
40
+    const name = '{{properCase name}}'
41
+    const actions = [{
42
+      type: 'add',
43
+      path: `src/components/${name}/index.vue`,
44
+      templateFile: 'plop-templates/component/index.hbs',
45
+      data: {
46
+        name: name,
47
+        template: data.blocks.includes('template'),
48
+        script: data.blocks.includes('script'),
49
+        style: data.blocks.includes('style')
50
+      }
51
+    }]
52
+
53
+    return actions
54
+  }
55
+}

+ 16 - 0
plop-templates/store/index.hbs

@@ -0,0 +1,16 @@
1
+{{#if state}}
2
+const state = {}
3
+{{/if}}
4
+
5
+{{#if mutations}}
6
+const mutations = {}
7
+{{/if}}
8
+
9
+{{#if actions}}
10
+const actions = {}
11
+{{/if}}
12
+
13
+export default {
14
+  namespaced: true,
15
+  {{options}}
16
+}

+ 62 - 0
plop-templates/store/prompt.js

@@ -0,0 +1,62 @@
1
+const { notEmpty } = require('../utils.js')
2
+
3
+module.exports = {
4
+  description: 'generate store',
5
+  prompts: [{
6
+    type: 'input',
7
+    name: 'name',
8
+    message: 'store name please',
9
+    validate: notEmpty('name')
10
+  },
11
+  {
12
+    type: 'checkbox',
13
+    name: 'blocks',
14
+    message: 'Blocks:',
15
+    choices: [{
16
+      name: 'state',
17
+      value: 'state',
18
+      checked: true
19
+    },
20
+    {
21
+      name: 'mutations',
22
+      value: 'mutations',
23
+      checked: true
24
+    },
25
+    {
26
+      name: 'actions',
27
+      value: 'actions',
28
+      checked: true
29
+    }
30
+    ],
31
+    validate(value) {
32
+      if (!value.includes('state') || !value.includes('mutations')) {
33
+        return 'store require at least state and mutations'
34
+      }
35
+      return true
36
+    }
37
+  }
38
+  ],
39
+  actions(data) {
40
+    const name = '{{name}}'
41
+    const { blocks } = data
42
+    const options = ['state', 'mutations']
43
+    const joinFlag = `,
44
+  `
45
+    if (blocks.length === 3) {
46
+      options.push('actions')
47
+    }
48
+
49
+    const actions = [{
50
+      type: 'add',
51
+      path: `src/store/modules/${name}.js`,
52
+      templateFile: 'plop-templates/store/index.hbs',
53
+      data: {
54
+        options: options.join(joinFlag),
55
+        state: blocks.includes('state'),
56
+        mutations: blocks.includes('mutations'),
57
+        actions: blocks.includes('actions')
58
+      }
59
+    }]
60
+    return actions
61
+  }
62
+}

+ 9 - 0
plop-templates/utils.js

@@ -0,0 +1,9 @@
1
+exports.notEmpty = name => {
2
+  return v => {
3
+    if (!v || v.trim === '') {
4
+      return `${name} is required`
5
+    } else {
6
+      return true
7
+    }
8
+  }
9
+}

+ 26 - 0
plop-templates/view/index.hbs

@@ -0,0 +1,26 @@
1
+{{#if template}}
2
+<template>
3
+  <div />
4
+</template>
5
+{{/if}}
6
+
7
+{{#if script}}
8
+<script>
9
+export default {
10
+  name: '{{ properCase name }}',
11
+  props: {},
12
+  data() {
13
+    return {}
14
+  },
15
+  created() {},
16
+  mounted() {},
17
+  methods: {}
18
+}
19
+</script>
20
+{{/if}}
21
+
22
+{{#if style}}
23
+<style lang="scss" scoped>
24
+
25
+</style>
26
+{{/if}}

+ 55 - 0
plop-templates/view/prompt.js

@@ -0,0 +1,55 @@
1
+const { notEmpty } = require('../utils.js')
2
+
3
+module.exports = {
4
+  description: 'generate a view',
5
+  prompts: [{
6
+    type: 'input',
7
+    name: 'name',
8
+    message: 'view name please',
9
+    validate: notEmpty('name')
10
+  },
11
+  {
12
+    type: 'checkbox',
13
+    name: 'blocks',
14
+    message: 'Blocks:',
15
+    choices: [{
16
+      name: '<template>',
17
+      value: 'template',
18
+      checked: true
19
+    },
20
+    {
21
+      name: '<script>',
22
+      value: 'script',
23
+      checked: true
24
+    },
25
+    {
26
+      name: 'style',
27
+      value: 'style',
28
+      checked: true
29
+    }
30
+    ],
31
+    validate(value) {
32
+      if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
33
+        return 'View require at least a <script> or <template> tag.'
34
+      }
35
+      return true
36
+    }
37
+  }
38
+  ],
39
+  actions: data => {
40
+    const name = '{{name}}'
41
+    const actions = [{
42
+      type: 'add',
43
+      path: `src/views/${name}/index.vue`,
44
+      templateFile: 'plop-templates/view/index.hbs',
45
+      data: {
46
+        name: name,
47
+        template: data.blocks.includes('template'),
48
+        script: data.blocks.includes('script'),
49
+        style: data.blocks.includes('style')
50
+      }
51
+    }]
52
+
53
+    return actions
54
+  }
55
+}

+ 9 - 0
plopfile.js

@@ -0,0 +1,9 @@
1
+const viewGenerator = require('./plop-templates/view/prompt')
2
+const componentGenerator = require('./plop-templates/component/prompt')
3
+const storeGenerator = require('./plop-templates/store/prompt.js')
4
+
5
+module.exports = function(plop) {
6
+  plop.setGenerator('view', viewGenerator)
7
+  plop.setGenerator('component', componentGenerator)
8
+  plop.setGenerator('store', storeGenerator)
9
+}

+ 5 - 0
postcss.config.js

@@ -0,0 +1,5 @@
1
+module.exports = {
2
+  plugins: {
3
+    autoprefixer: {}
4
+  }
5
+}

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

@@ -0,0 +1,40 @@
1
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+    "http://www.w3.org/TR/html4/loose.dtd">
3
+<html>
4
+    <head>
5
+        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
6
+        <title></title>
7
+        <style type="text/css">
8
+            *{color: #838383;margin: 0;padding: 0}
9
+            html,body {font-size: 12px;overflow: hidden; }
10
+            .content{padding:5px 0 0 15px;}
11
+            input{width:210px;height:21px;line-height:21px;margin-left: 4px;}
12
+        </style>
13
+    </head>
14
+    <body>
15
+        <div class="content">
16
+            <span><var id="lang_input_anchorName"></var></span><input id="anchorName"  value="" />
17
+        </div>
18
+        <script type="text/javascript" src="../internal.js"></script>
19
+        <script type="text/javascript">
20
+            var anchorInput = $G('anchorName'),
21
+                node = editor.selection.getRange().getClosedNode();
22
+            if(node && node.tagName == 'IMG' && (node = node.getAttribute('anchorname'))){
23
+                anchorInput.value = node;
24
+            }
25
+            anchorInput.onkeydown = function(evt){
26
+                evt = evt || window.event;
27
+                if(evt.keyCode == 13){
28
+                    editor.execCommand('anchor', anchorInput.value);
29
+                    dialog.close();
30
+                    domUtils.preventDefault(evt)
31
+                }
32
+            };
33
+            dialog.onok = function (){
34
+                editor.execCommand('anchor', anchorInput.value);
35
+                dialog.close();
36
+            };
37
+            $focus(anchorInput);
38
+        </script>
39
+    </body>
40
+</html>

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

@@ -0,0 +1,681 @@
1
+@charset "utf-8";
2
+/* dialog样式 */
3
+.wrapper {
4
+    zoom: 1;
5
+    width: 630px;
6
+    *width: 626px;
7
+    height: 380px;
8
+    margin: 0 auto;
9
+    padding: 10px;
10
+    position: relative;
11
+    font-family: sans-serif;
12
+}
13
+
14
+/*tab样式框大小*/
15
+.tabhead {
16
+    float:left;
17
+}
18
+.tabbody {
19
+    width: 100%;
20
+    height: 346px;
21
+    position: relative;
22
+    clear: both;
23
+}
24
+
25
+.tabbody .panel {
26
+    position: absolute;
27
+    width: 0;
28
+    height: 0;
29
+    background: #fff;
30
+    overflow: hidden;
31
+    display: none;
32
+}
33
+
34
+.tabbody .panel.focus {
35
+    width: 100%;
36
+    height: 346px;
37
+    display: block;
38
+}
39
+
40
+/* 上传附件 */
41
+.tabbody #upload.panel {
42
+    width: 0;
43
+    height: 0;
44
+    overflow: hidden;
45
+    position: absolute !important;
46
+    clip: rect(1px, 1px, 1px, 1px);
47
+    background: #fff;
48
+    display: block;
49
+}
50
+
51
+.tabbody #upload.panel.focus {
52
+    width: 100%;
53
+    height: 346px;
54
+    display: block;
55
+    clip: auto;
56
+}
57
+
58
+#upload .queueList {
59
+    margin: 0;
60
+    width: 100%;
61
+    height: 100%;
62
+    position: absolute;
63
+    overflow: hidden;
64
+}
65
+
66
+#upload p {
67
+    margin: 0;
68
+}
69
+
70
+.element-invisible {
71
+    width: 0 !important;
72
+    height: 0 !important;
73
+    border: 0;
74
+    padding: 0;
75
+    margin: 0;
76
+    overflow: hidden;
77
+    position: absolute !important;
78
+    clip: rect(1px, 1px, 1px, 1px);
79
+}
80
+
81
+#upload .placeholder {
82
+    margin: 10px;
83
+    border: 2px dashed #e6e6e6;
84
+    *border: 0px dashed #e6e6e6;
85
+    height: 172px;
86
+    padding-top: 150px;
87
+    text-align: center;
88
+    background: url(./images/image.png) center 70px no-repeat;
89
+    color: #cccccc;
90
+    font-size: 18px;
91
+    position: relative;
92
+    top:0;
93
+    *top: 10px;
94
+}
95
+
96
+#upload .placeholder .webuploader-pick {
97
+    font-size: 18px;
98
+    background: #00b7ee;
99
+    border-radius: 3px;
100
+    line-height: 44px;
101
+    padding: 0 30px;
102
+    *width: 120px;
103
+    color: #fff;
104
+    display: inline-block;
105
+    margin: 0 auto 20px auto;
106
+    cursor: pointer;
107
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
108
+}
109
+
110
+#upload .placeholder .webuploader-pick-hover {
111
+    background: #00a2d4;
112
+}
113
+
114
+
115
+#filePickerContainer {
116
+    text-align: center;
117
+}
118
+
119
+#upload .placeholder .flashTip {
120
+    color: #666666;
121
+    font-size: 12px;
122
+    position: absolute;
123
+    width: 100%;
124
+    text-align: center;
125
+    bottom: 20px;
126
+}
127
+
128
+#upload .placeholder .flashTip a {
129
+    color: #0785d1;
130
+    text-decoration: none;
131
+}
132
+
133
+#upload .placeholder .flashTip a:hover {
134
+    text-decoration: underline;
135
+}
136
+
137
+#upload .placeholder.webuploader-dnd-over {
138
+    border-color: #999999;
139
+}
140
+
141
+#upload .filelist {
142
+    list-style: none;
143
+    margin: 0;
144
+    padding: 0;
145
+    overflow-x: hidden;
146
+    overflow-y: auto;
147
+    position: relative;
148
+    height: 300px;
149
+}
150
+
151
+#upload .filelist:after {
152
+    content: '';
153
+    display: block;
154
+    width: 0;
155
+    height: 0;
156
+    overflow: hidden;
157
+    clear: both;
158
+}
159
+
160
+#upload .filelist li {
161
+    width: 113px;
162
+    height: 113px;
163
+    background: url(./images/bg.png);
164
+    text-align: center;
165
+    margin: 9px 0 0 9px;
166
+    *margin: 6px 0 0 6px;
167
+    position: relative;
168
+    display: block;
169
+    float: left;
170
+    overflow: hidden;
171
+    font-size: 12px;
172
+}
173
+
174
+#upload .filelist li p.log {
175
+    position: relative;
176
+    top: -45px;
177
+}
178
+
179
+#upload .filelist li p.title {
180
+    position: absolute;
181
+    top: 0;
182
+    left: 0;
183
+    width: 100%;
184
+    overflow: hidden;
185
+    white-space: nowrap;
186
+    text-overflow: ellipsis;
187
+    top: 5px;
188
+    text-indent: 5px;
189
+    text-align: left;
190
+}
191
+
192
+#upload .filelist li p.progress {
193
+    position: absolute;
194
+    width: 100%;
195
+    bottom: 0;
196
+    left: 0;
197
+    height: 8px;
198
+    overflow: hidden;
199
+    z-index: 50;
200
+    margin: 0;
201
+    border-radius: 0;
202
+    background: none;
203
+    -webkit-box-shadow: 0 0 0;
204
+}
205
+
206
+#upload .filelist li p.progress span {
207
+    display: none;
208
+    overflow: hidden;
209
+    width: 0;
210
+    height: 100%;
211
+    background: #1483d8 url(./images/progress.png) repeat-x;
212
+
213
+    -webit-transition: width 200ms linear;
214
+    -moz-transition: width 200ms linear;
215
+    -o-transition: width 200ms linear;
216
+    -ms-transition: width 200ms linear;
217
+    transition: width 200ms linear;
218
+
219
+    -webkit-animation: progressmove 2s linear infinite;
220
+    -moz-animation: progressmove 2s linear infinite;
221
+    -o-animation: progressmove 2s linear infinite;
222
+    -ms-animation: progressmove 2s linear infinite;
223
+    animation: progressmove 2s linear infinite;
224
+
225
+    -webkit-transform: translateZ(0);
226
+}
227
+
228
+@-webkit-keyframes progressmove {
229
+    0% {
230
+        background-position: 0 0;
231
+    }
232
+    100% {
233
+        background-position: 17px 0;
234
+    }
235
+}
236
+
237
+@-moz-keyframes progressmove {
238
+    0% {
239
+        background-position: 0 0;
240
+    }
241
+    100% {
242
+        background-position: 17px 0;
243
+    }
244
+}
245
+
246
+@keyframes progressmove {
247
+    0% {
248
+        background-position: 0 0;
249
+    }
250
+    100% {
251
+        background-position: 17px 0;
252
+    }
253
+}
254
+
255
+#upload .filelist li p.imgWrap {
256
+    position: relative;
257
+    z-index: 2;
258
+    line-height: 113px;
259
+    vertical-align: middle;
260
+    overflow: hidden;
261
+    width: 113px;
262
+    height: 113px;
263
+
264
+    -webkit-transform-origin: 50% 50%;
265
+    -moz-transform-origin: 50% 50%;
266
+    -o-transform-origin: 50% 50%;
267
+    -ms-transform-origin: 50% 50%;
268
+    transform-origin: 50% 50%;
269
+
270
+    -webit-transition: 200ms ease-out;
271
+    -moz-transition: 200ms ease-out;
272
+    -o-transition: 200ms ease-out;
273
+    -ms-transition: 200ms ease-out;
274
+    transition: 200ms ease-out;
275
+}
276
+#upload .filelist li p.imgWrap.notimage {
277
+    margin-top: 0;
278
+    width: 111px;
279
+    height: 111px;
280
+    border: 1px #eeeeee solid;
281
+}
282
+#upload .filelist li p.imgWrap.notimage i.file-preview {
283
+    margin-top: 15px;
284
+}
285
+
286
+#upload .filelist li img {
287
+    width: 100%;
288
+}
289
+
290
+#upload .filelist li p.error {
291
+    background: #f43838;
292
+    color: #fff;
293
+    position: absolute;
294
+    bottom: 0;
295
+    left: 0;
296
+    height: 28px;
297
+    line-height: 28px;
298
+    width: 100%;
299
+    z-index: 100;
300
+    display:none;
301
+}
302
+
303
+#upload .filelist li .success {
304
+    display: block;
305
+    position: absolute;
306
+    left: 0;
307
+    bottom: 0;
308
+    height: 40px;
309
+    width: 100%;
310
+    z-index: 200;
311
+    background: url(./images/success.png) no-repeat right bottom;
312
+    background-image: url(./images/success.gif) \9;
313
+}
314
+
315
+#upload .filelist li.filePickerBlock {
316
+    width: 113px;
317
+    height: 113px;
318
+    background: url(./images/image.png) no-repeat center 12px;
319
+    border: 1px solid #eeeeee;
320
+    border-radius: 0;
321
+}
322
+#upload .filelist li.filePickerBlock div.webuploader-pick  {
323
+    width: 100%;
324
+    height: 100%;
325
+    margin: 0;
326
+    padding: 0;
327
+    opacity: 0;
328
+    background: none;
329
+    font-size: 0;
330
+}
331
+
332
+#upload .filelist div.file-panel {
333
+    position: absolute;
334
+    height: 0;
335
+    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0;
336
+    background: rgba(0, 0, 0, 0.5);
337
+    width: 100%;
338
+    top: 0;
339
+    left: 0;
340
+    overflow: hidden;
341
+    z-index: 300;
342
+}
343
+
344
+#upload .filelist div.file-panel span {
345
+    width: 24px;
346
+    height: 24px;
347
+    display: inline;
348
+    float: right;
349
+    text-indent: -9999px;
350
+    overflow: hidden;
351
+    background: url(./images/icons.png) no-repeat;
352
+    background: url(./images/icons.gif) no-repeat \9;
353
+    margin: 5px 1px 1px;
354
+    cursor: pointer;
355
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
356
+    -webkit-user-select: none;
357
+    -moz-user-select: none;
358
+    -ms-user-select: none;
359
+    user-select: none;
360
+}
361
+
362
+#upload .filelist div.file-panel span.rotateLeft {
363
+    display:none;
364
+    background-position: 0 -24px;
365
+}
366
+
367
+#upload .filelist div.file-panel span.rotateLeft:hover {
368
+    background-position: 0 0;
369
+}
370
+
371
+#upload .filelist div.file-panel span.rotateRight {
372
+    display:none;
373
+    background-position: -24px -24px;
374
+}
375
+
376
+#upload .filelist div.file-panel span.rotateRight:hover {
377
+    background-position: -24px 0;
378
+}
379
+
380
+#upload .filelist div.file-panel span.cancel {
381
+    background-position: -48px -24px;
382
+}
383
+
384
+#upload .filelist div.file-panel span.cancel:hover {
385
+    background-position: -48px 0;
386
+}
387
+
388
+#upload .statusBar {
389
+    height: 45px;
390
+    border-bottom: 1px solid #dadada;
391
+    margin: 0 10px;
392
+    padding: 0;
393
+    line-height: 45px;
394
+    vertical-align: middle;
395
+    position: relative;
396
+}
397
+
398
+#upload .statusBar .progress {
399
+    border: 1px solid #1483d8;
400
+    width: 198px;
401
+    background: #fff;
402
+    height: 18px;
403
+    position: absolute;
404
+    top: 12px;
405
+    display: none;
406
+    text-align: center;
407
+    line-height: 18px;
408
+    color: #6dbfff;
409
+    margin: 0 10px 0 0;
410
+}
411
+#upload .statusBar .progress span.percentage {
412
+    width: 0;
413
+    height: 100%;
414
+    left: 0;
415
+    top: 0;
416
+    background: #1483d8;
417
+    position: absolute;
418
+}
419
+#upload .statusBar .progress span.text {
420
+    position: relative;
421
+    z-index: 10;
422
+}
423
+
424
+#upload .statusBar .info {
425
+    display: inline-block;
426
+    font-size: 14px;
427
+    color: #666666;
428
+}
429
+
430
+#upload .statusBar .btns {
431
+    position: absolute;
432
+    top: 7px;
433
+    right: 0;
434
+    line-height: 30px;
435
+}
436
+
437
+#filePickerBtn {
438
+    display: inline-block;
439
+    float: left;
440
+}
441
+#upload .statusBar .btns .webuploader-pick,
442
+#upload .statusBar .btns .uploadBtn,
443
+#upload .statusBar .btns .uploadBtn.state-uploading,
444
+#upload .statusBar .btns .uploadBtn.state-paused {
445
+    background: #ffffff;
446
+    border: 1px solid #cfcfcf;
447
+    color: #565656;
448
+    padding: 0 18px;
449
+    display: inline-block;
450
+    border-radius: 3px;
451
+    margin-left: 10px;
452
+    cursor: pointer;
453
+    font-size: 14px;
454
+    float: left;
455
+    -webkit-user-select: none;
456
+    -moz-user-select: none;
457
+    -ms-user-select: none;
458
+    user-select: none;
459
+}
460
+#upload .statusBar .btns .webuploader-pick-hover,
461
+#upload .statusBar .btns .uploadBtn:hover,
462
+#upload .statusBar .btns .uploadBtn.state-uploading:hover,
463
+#upload .statusBar .btns .uploadBtn.state-paused:hover {
464
+    background: #f0f0f0;
465
+}
466
+
467
+#upload .statusBar .btns .uploadBtn,
468
+#upload .statusBar .btns .uploadBtn.state-paused{
469
+    background: #00b7ee;
470
+    color: #fff;
471
+    border-color: transparent;
472
+}
473
+#upload .statusBar .btns .uploadBtn:hover,
474
+#upload .statusBar .btns .uploadBtn.state-paused:hover{
475
+    background: #00a2d4;
476
+}
477
+
478
+#upload .statusBar .btns .uploadBtn.disabled {
479
+    pointer-events: none;
480
+    filter:alpha(opacity=60);
481
+    -moz-opacity:0.6;
482
+    -khtml-opacity: 0.6;
483
+    opacity: 0.6;
484
+}
485
+
486
+
487
+
488
+/* 图片管理样式 */
489
+#online {
490
+    width: 100%;
491
+    height: 336px;
492
+    padding: 10px 0 0 0;
493
+}
494
+#online #fileList{
495
+    width: 100%;
496
+    height: 100%;
497
+    overflow-x: hidden;
498
+    overflow-y: auto;
499
+    position: relative;
500
+}
501
+#online ul {
502
+    display: block;
503
+    list-style: none;
504
+    margin: 0;
505
+    padding: 0;
506
+}
507
+#online li {
508
+    float: left;
509
+    display: block;
510
+    list-style: none;
511
+    padding: 0;
512
+    width: 113px;
513
+    height: 113px;
514
+    margin: 0 0 9px 9px;
515
+    *margin: 0 0 6px 6px;
516
+    background-color: #eee;
517
+    overflow: hidden;
518
+    cursor: pointer;
519
+    position: relative;
520
+}
521
+#online li.clearFloat {
522
+    float: none;
523
+    clear: both;
524
+    display: block;
525
+    width:0;
526
+    height:0;
527
+    margin: 0;
528
+    padding: 0;
529
+}
530
+#online li img {
531
+    cursor: pointer;
532
+}
533
+#online li div.file-wrapper {
534
+    cursor: pointer;
535
+    position: absolute;
536
+    display: block;
537
+    width: 111px;
538
+    height: 111px;
539
+    border: 1px solid #eee;
540
+    background: url("./images/bg.png") repeat;
541
+}
542
+#online li div span.file-title{
543
+    display: block;
544
+    padding: 0 3px;
545
+    margin: 3px 0 0 0;
546
+    font-size: 12px;
547
+    height: 13px;
548
+    color: #555555;
549
+    text-align: center;
550
+    width: 107px;
551
+    white-space: nowrap;
552
+    word-break: break-all;
553
+    overflow: hidden;
554
+    text-overflow: ellipsis;
555
+}
556
+#online li .icon {
557
+    cursor: pointer;
558
+    width: 113px;
559
+    height: 113px;
560
+    position: absolute;
561
+    top: 0;
562
+    left: 0;
563
+    z-index: 2;
564
+    border: 0;
565
+    background-repeat: no-repeat;
566
+}
567
+#online li .icon:hover {
568
+    width: 107px;
569
+    height: 107px;
570
+    border: 3px solid #1094fa;
571
+}
572
+#online li.selected .icon {
573
+    background-image: url(images/success.png);
574
+    background-image: url(images/success.gif) \9;
575
+    background-position: 75px 75px;
576
+}
577
+#online li.selected .icon:hover {
578
+    width: 107px;
579
+    height: 107px;
580
+    border: 3px solid #1094fa;
581
+    background-position: 72px 72px;
582
+}
583
+
584
+
585
+/* 在线文件的文件预览图标 */
586
+i.file-preview {
587
+    display: block;
588
+    margin: 10px auto;
589
+    width: 70px;
590
+    height: 70px;
591
+    background-image: url("./images/file-icons.png");
592
+    background-image: url("./images/file-icons.gif") \9;
593
+    background-position: -140px center;
594
+    background-repeat: no-repeat;
595
+}
596
+i.file-preview.file-type-dir{
597
+    background-position: 0 center;
598
+}
599
+i.file-preview.file-type-file{
600
+    background-position: -140px center;
601
+}
602
+i.file-preview.file-type-filelist{
603
+    background-position: -210px center;
604
+}
605
+i.file-preview.file-type-zip,
606
+i.file-preview.file-type-rar,
607
+i.file-preview.file-type-7z,
608
+i.file-preview.file-type-tar,
609
+i.file-preview.file-type-gz,
610
+i.file-preview.file-type-bz2{
611
+    background-position: -280px center;
612
+}
613
+i.file-preview.file-type-xls,
614
+i.file-preview.file-type-xlsx{
615
+    background-position: -350px center;
616
+}
617
+i.file-preview.file-type-doc,
618
+i.file-preview.file-type-docx{
619
+    background-position: -420px center;
620
+}
621
+i.file-preview.file-type-ppt,
622
+i.file-preview.file-type-pptx{
623
+    background-position: -490px center;
624
+}
625
+i.file-preview.file-type-vsd{
626
+    background-position: -560px center;
627
+}
628
+i.file-preview.file-type-pdf{
629
+    background-position: -630px center;
630
+}
631
+i.file-preview.file-type-txt,
632
+i.file-preview.file-type-md,
633
+i.file-preview.file-type-json,
634
+i.file-preview.file-type-htm,
635
+i.file-preview.file-type-xml,
636
+i.file-preview.file-type-html,
637
+i.file-preview.file-type-js,
638
+i.file-preview.file-type-css,
639
+i.file-preview.file-type-php,
640
+i.file-preview.file-type-jsp,
641
+i.file-preview.file-type-asp{
642
+    background-position: -700px center;
643
+}
644
+i.file-preview.file-type-apk{
645
+    background-position: -770px center;
646
+}
647
+i.file-preview.file-type-exe{
648
+    background-position: -840px center;
649
+}
650
+i.file-preview.file-type-ipa{
651
+    background-position: -910px center;
652
+}
653
+i.file-preview.file-type-mp4,
654
+i.file-preview.file-type-swf,
655
+i.file-preview.file-type-mkv,
656
+i.file-preview.file-type-avi,
657
+i.file-preview.file-type-flv,
658
+i.file-preview.file-type-mov,
659
+i.file-preview.file-type-mpg,
660
+i.file-preview.file-type-mpeg,
661
+i.file-preview.file-type-ogv,
662
+i.file-preview.file-type-webm,
663
+i.file-preview.file-type-rm,
664
+i.file-preview.file-type-rmvb{
665
+    background-position: -980px center;
666
+}
667
+i.file-preview.file-type-ogg,
668
+i.file-preview.file-type-wav,
669
+i.file-preview.file-type-wmv,
670
+i.file-preview.file-type-mid,
671
+i.file-preview.file-type-mp3{
672
+    background-position: -1050px center;
673
+}
674
+i.file-preview.file-type-jpg,
675
+i.file-preview.file-type-jpeg,
676
+i.file-preview.file-type-gif,
677
+i.file-preview.file-type-bmp,
678
+i.file-preview.file-type-png,
679
+i.file-preview.file-type-psd{
680
+    background-position: -140px center;
681
+}

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

@@ -0,0 +1,60 @@
1
+<!doctype html>
2
+<html>
3
+<head>
4
+    <meta charset="UTF-8">
5
+    <title>ueditor图片对话框</title>
6
+    <script type="text/javascript" src="../internal.js"></script>
7
+
8
+    <!-- jquery -->
9
+    <script type="text/javascript" src="../../third-party/jquery-1.10.2.min.js"></script>
10
+
11
+    <!-- webuploader -->
12
+    <script src="../../third-party/webuploader/webuploader.min.js"></script>
13
+    <link rel="stylesheet" type="text/css" href="../../third-party/webuploader/webuploader.css">
14
+
15
+    <!-- attachment dialog -->
16
+    <link rel="stylesheet" href="attachment.css" type="text/css" />
17
+</head>
18
+<body>
19
+
20
+    <div class="wrapper">
21
+        <div id="tabhead" class="tabhead">
22
+            <span class="tab focus" data-content-id="upload"><var id="lang_tab_upload"></var></span>
23
+            <span class="tab" data-content-id="online"><var id="lang_tab_online"></var></span>
24
+        </div>
25
+        <div id="tabbody" class="tabbody">
26
+            <!-- 上传图片 -->
27
+            <div id="upload" class="panel focus">
28
+                <div id="queueList" class="queueList">
29
+                    <div class="statusBar element-invisible">
30
+                        <div class="progress">
31
+                            <span class="text">0%</span>
32
+                            <span class="percentage"></span>
33
+                        </div><div class="info"></div>
34
+                        <div class="btns">
35
+                            <div id="filePickerBtn"></div>
36
+                            <div class="uploadBtn"><var id="lang_start_upload"></var></div>
37
+                        </div>
38
+                    </div>
39
+                    <div id="dndArea" class="placeholder">
40
+                        <div class="filePickerContainer">
41
+                            <div id="filePickerReady"></div>
42
+                        </div>
43
+                    </div>
44
+                    <ul class="filelist element-invisible">
45
+                        <li id="filePickerBlock" class="filePickerBlock"></li>
46
+                    </ul>
47
+                </div>
48
+            </div>
49
+
50
+            <!-- 在线图片 -->
51
+            <div id="online" class="panel">
52
+                <div id="fileList"><var id="lang_imgLoading"></var></div>
53
+            </div>
54
+
55
+        </div>
56
+    </div>
57
+    <script type="text/javascript" src="attachment.js"></script>
58
+
59
+</body>
60
+</html>

+ 760 - 0
public/UEditor/dialogs/attachment/attachment.js

@@ -0,0 +1,760 @@
1
+/**
2
+ * User: Jinqn
3
+ * Date: 14-04-08
4
+ * Time: 下午16:34
5
+ * 上传图片对话框逻辑代码,包括tab: 远程图片/上传图片/在线图片/搜索图片
6
+ */
7
+
8
+(function () {
9
+
10
+    var uploadFile,
11
+        onlineFile;
12
+
13
+    window.onload = function () {
14
+        initTabs();
15
+        initButtons();
16
+    };
17
+
18
+    /* 初始化tab标签 */
19
+    function initTabs() {
20
+        var tabs = $G('tabhead').children;
21
+        for (var i = 0; i < tabs.length; i++) {
22
+            domUtils.on(tabs[i], "click", function (e) {
23
+                var target = e.target || e.srcElement;
24
+                setTabFocus(target.getAttribute('data-content-id'));
25
+            });
26
+        }
27
+
28
+        setTabFocus('upload');
29
+    }
30
+
31
+    /* 初始化tabbody */
32
+    function setTabFocus(id) {
33
+        if(!id) return;
34
+        var i, bodyId, tabs = $G('tabhead').children;
35
+        for (i = 0; i < tabs.length; i++) {
36
+            bodyId = tabs[i].getAttribute('data-content-id')
37
+            if (bodyId == id) {
38
+                domUtils.addClass(tabs[i], 'focus');
39
+                domUtils.addClass($G(bodyId), 'focus');
40
+            } else {
41
+                domUtils.removeClasses(tabs[i], 'focus');
42
+                domUtils.removeClasses($G(bodyId), 'focus');
43
+            }
44
+        }
45
+        switch (id) {
46
+            case 'upload':
47
+                uploadFile = uploadFile || new UploadFile('queueList');
48
+                break;
49
+            case 'online':
50
+                onlineFile = onlineFile || new OnlineFile('fileList');
51
+                break;
52
+        }
53
+    }
54
+
55
+    /* 初始化onok事件 */
56
+    function initButtons() {
57
+
58
+        dialog.onok = function () {
59
+            var list = [], id, tabs = $G('tabhead').children;
60
+            for (var i = 0; i < tabs.length; i++) {
61
+                if (domUtils.hasClass(tabs[i], 'focus')) {
62
+                    id = tabs[i].getAttribute('data-content-id');
63
+                    break;
64
+                }
65
+            }
66
+
67
+            switch (id) {
68
+                case 'upload':
69
+                    list = uploadFile.getInsertList();
70
+                    var count = uploadFile.getQueueCount();
71
+                    if (count) {
72
+                        $('.info', '#queueList').html('<span style="color:red;">' + '还有2个未上传文件'.replace(/[\d]/, count) + '</span>');
73
+                        return false;
74
+                    }
75
+                    break;
76
+                case 'online':
77
+                    list = onlineFile.getInsertList();
78
+                    break;
79
+            }
80
+
81
+            editor.execCommand('insertfile', list);
82
+        };
83
+    }
84
+
85
+
86
+    /* 上传附件 */
87
+    function UploadFile(target) {
88
+        this.$wrap = target.constructor == String ? $('#' + target) : $(target);
89
+        this.init();
90
+    }
91
+    UploadFile.prototype = {
92
+        init: function () {
93
+            this.fileList = [];
94
+            this.initContainer();
95
+            this.initUploader();
96
+        },
97
+        initContainer: function () {
98
+            this.$queue = this.$wrap.find('.filelist');
99
+        },
100
+        /* 初始化容器 */
101
+        initUploader: function () {
102
+            var _this = this,
103
+                $ = jQuery,    // just in case. Make sure it's not an other libaray.
104
+                $wrap = _this.$wrap,
105
+            // 图片容器
106
+                $queue = $wrap.find('.filelist'),
107
+            // 状态栏,包括进度和控制按钮
108
+                $statusBar = $wrap.find('.statusBar'),
109
+            // 文件总体选择信息。
110
+                $info = $statusBar.find('.info'),
111
+            // 上传按钮
112
+                $upload = $wrap.find('.uploadBtn'),
113
+            // 上传按钮
114
+                $filePickerBtn = $wrap.find('.filePickerBtn'),
115
+            // 上传按钮
116
+                $filePickerBlock = $wrap.find('.filePickerBlock'),
117
+            // 没选择文件之前的内容。
118
+                $placeHolder = $wrap.find('.placeholder'),
119
+            // 总体进度条
120
+                $progress = $statusBar.find('.progress').hide(),
121
+            // 添加的文件数量
122
+                fileCount = 0,
123
+            // 添加的文件总大小
124
+                fileSize = 0,
125
+            // 优化retina, 在retina下这个值是2
126
+                ratio = window.devicePixelRatio || 1,
127
+            // 缩略图大小
128
+                thumbnailWidth = 113 * ratio,
129
+                thumbnailHeight = 113 * ratio,
130
+            // 可能有pedding, ready, uploading, confirm, done.
131
+                state = '',
132
+            // 所有文件的进度信息,key为file id
133
+                percentages = {},
134
+                supportTransition = (function () {
135
+                    var s = document.createElement('p').style,
136
+                        r = 'transition' in s ||
137
+                            'WebkitTransition' in s ||
138
+                            'MozTransition' in s ||
139
+                            'msTransition' in s ||
140
+                            'OTransition' in s;
141
+                    s = null;
142
+                    return r;
143
+                })(),
144
+            // WebUploader实例
145
+                uploader,
146
+                actionUrl = editor.getActionUrl(editor.getOpt('fileActionName')),
147
+                fileMaxSize = editor.getOpt('fileMaxSize'),
148
+                acceptExtensions = (editor.getOpt('fileAllowFiles') || []).join('').replace(/\./g, ',').replace(/^[,]/, '');;
149
+
150
+            if (!WebUploader.Uploader.support()) {
151
+                $('#filePickerReady').after($('<div>').html(lang.errorNotSupport)).hide();
152
+                return;
153
+            } else if (!editor.getOpt('fileActionName')) {
154
+                $('#filePickerReady').after($('<div>').html(lang.errorLoadConfig)).hide();
155
+                return;
156
+            }
157
+
158
+            uploader = _this.uploader = WebUploader.create({
159
+                pick: {
160
+                    id: '#filePickerReady',
161
+                    label: lang.uploadSelectFile
162
+                },
163
+                swf: '../../third-party/webuploader/Uploader.swf',
164
+                server: actionUrl,
165
+                fileVal: editor.getOpt('fileFieldName'),
166
+                duplicate: true,
167
+                fileSingleSizeLimit: fileMaxSize,
168
+                compress: false
169
+            });
170
+            uploader.addButton({
171
+                id: '#filePickerBlock'
172
+            });
173
+            uploader.addButton({
174
+                id: '#filePickerBtn',
175
+                label: lang.uploadAddFile
176
+            });
177
+
178
+            setState('pedding');
179
+
180
+            // 当有文件添加进来时执行,负责view的创建
181
+            function addFile(file) {
182
+                var $li = $('<li id="' + file.id + '">' +
183
+                        '<p class="title">' + file.name + '</p>' +
184
+                        '<p class="imgWrap"></p>' +
185
+                        '<p class="progress"><span></span></p>' +
186
+                        '</li>'),
187
+
188
+                    $btns = $('<div class="file-panel">' +
189
+                        '<span class="cancel">' + lang.uploadDelete + '</span>' +
190
+                        '<span class="rotateRight">' + lang.uploadTurnRight + '</span>' +
191
+                        '<span class="rotateLeft">' + lang.uploadTurnLeft + '</span></div>').appendTo($li),
192
+                    $prgress = $li.find('p.progress span'),
193
+                    $wrap = $li.find('p.imgWrap'),
194
+                    $info = $('<p class="error"></p>').hide().appendTo($li),
195
+
196
+                    showError = function (code) {
197
+                        switch (code) {
198
+                            case 'exceed_size':
199
+                                text = lang.errorExceedSize;
200
+                                break;
201
+                            case 'interrupt':
202
+                                text = lang.errorInterrupt;
203
+                                break;
204
+                            case 'http':
205
+                                text = lang.errorHttp;
206
+                                break;
207
+                            case 'not_allow_type':
208
+                                text = lang.errorFileType;
209
+                                break;
210
+                            default:
211
+                                text = lang.errorUploadRetry;
212
+                                break;
213
+                        }
214
+                        $info.text(text).show();
215
+                    };
216
+
217
+                if (file.getStatus() === 'invalid') {
218
+                    showError(file.statusText);
219
+                } else {
220
+                    $wrap.text(lang.uploadPreview);
221
+                    if ('|png|jpg|jpeg|bmp|gif|'.indexOf('|'+file.ext.toLowerCase()+'|') == -1) {
222
+                        $wrap.empty().addClass('notimage').append('<i class="file-preview file-type-' + file.ext.toLowerCase() + '"></i>' +
223
+                        '<span class="file-title" title="' + file.name + '">' + file.name + '</span>');
224
+                    } else {
225
+                        if (browser.ie && browser.version <= 7) {
226
+                            $wrap.text(lang.uploadNoPreview);
227
+                        } else {
228
+                            uploader.makeThumb(file, function (error, src) {
229
+                                if (error || !src) {
230
+                                    $wrap.text(lang.uploadNoPreview);
231
+                                } else {
232
+                                    var $img = $('<img src="' + src + '">');
233
+                                    $wrap.empty().append($img);
234
+                                    $img.on('error', function () {
235
+                                        $wrap.text(lang.uploadNoPreview);
236
+                                    });
237
+                                }
238
+                            }, thumbnailWidth, thumbnailHeight);
239
+                        }
240
+                    }
241
+                    percentages[ file.id ] = [ file.size, 0 ];
242
+                    file.rotation = 0;
243
+
244
+                    /* 检查文件格式 */
245
+                    if (!file.ext || acceptExtensions.indexOf(file.ext.toLowerCase()) == -1) {
246
+                        showError('not_allow_type');
247
+                        uploader.removeFile(file);
248
+                    }
249
+                }
250
+
251
+                file.on('statuschange', function (cur, prev) {
252
+                    if (prev === 'progress') {
253
+                        $prgress.hide().width(0);
254
+                    } else if (prev === 'queued') {
255
+                        $li.off('mouseenter mouseleave');
256
+                        $btns.remove();
257
+                    }
258
+                    // 成功
259
+                    if (cur === 'error' || cur === 'invalid') {
260
+                        showError(file.statusText);
261
+                        percentages[ file.id ][ 1 ] = 1;
262
+                    } else if (cur === 'interrupt') {
263
+                        showError('interrupt');
264
+                    } else if (cur === 'queued') {
265
+                        percentages[ file.id ][ 1 ] = 0;
266
+                    } else if (cur === 'progress') {
267
+                        $info.hide();
268
+                        $prgress.css('display', 'block');
269
+                    } else if (cur === 'complete') {
270
+                    }
271
+
272
+                    $li.removeClass('state-' + prev).addClass('state-' + cur);
273
+                });
274
+
275
+                $li.on('mouseenter', function () {
276
+                    $btns.stop().animate({height: 30});
277
+                });
278
+                $li.on('mouseleave', function () {
279
+                    $btns.stop().animate({height: 0});
280
+                });
281
+
282
+                $btns.on('click', 'span', function () {
283
+                    var index = $(this).index(),
284
+                        deg;
285
+
286
+                    switch (index) {
287
+                        case 0:
288
+                            uploader.removeFile(file);
289
+                            return;
290
+                        case 1:
291
+                            file.rotation += 90;
292
+                            break;
293
+                        case 2:
294
+                            file.rotation -= 90;
295
+                            break;
296
+                    }
297
+
298
+                    if (supportTransition) {
299
+                        deg = 'rotate(' + file.rotation + 'deg)';
300
+                        $wrap.css({
301
+                            '-webkit-transform': deg,
302
+                            '-mos-transform': deg,
303
+                            '-o-transform': deg,
304
+                            'transform': deg
305
+                        });
306
+                    } else {
307
+                        $wrap.css('filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation=' + (~~((file.rotation / 90) % 4 + 4) % 4) + ')');
308
+                    }
309
+
310
+                });
311
+
312
+                $li.insertBefore($filePickerBlock);
313
+            }
314
+
315
+            // 负责view的销毁
316
+            function removeFile(file) {
317
+                var $li = $('#' + file.id);
318
+                delete percentages[ file.id ];
319
+                updateTotalProgress();
320
+                $li.off().find('.file-panel').off().end().remove();
321
+            }
322
+
323
+            function updateTotalProgress() {
324
+                var loaded = 0,
325
+                    total = 0,
326
+                    spans = $progress.children(),
327
+                    percent;
328
+
329
+                $.each(percentages, function (k, v) {
330
+                    total += v[ 0 ];
331
+                    loaded += v[ 0 ] * v[ 1 ];
332
+                });
333
+
334
+                percent = total ? loaded / total : 0;
335
+
336
+                spans.eq(0).text(Math.round(percent * 100) + '%');
337
+                spans.eq(1).css('width', Math.round(percent * 100) + '%');
338
+                updateStatus();
339
+            }
340
+
341
+            function setState(val, files) {
342
+
343
+                if (val != state) {
344
+
345
+                    var stats = uploader.getStats();
346
+
347
+                    $upload.removeClass('state-' + state);
348
+                    $upload.addClass('state-' + val);
349
+
350
+                    switch (val) {
351
+
352
+                        /* 未选择文件 */
353
+                        case 'pedding':
354
+                            $queue.addClass('element-invisible');
355
+                            $statusBar.addClass('element-invisible');
356
+                            $placeHolder.removeClass('element-invisible');
357
+                            $progress.hide(); $info.hide();
358
+                            uploader.refresh();
359
+                            break;
360
+
361
+                        /* 可以开始上传 */
362
+                        case 'ready':
363
+                            $placeHolder.addClass('element-invisible');
364
+                            $queue.removeClass('element-invisible');
365
+                            $statusBar.removeClass('element-invisible');
366
+                            $progress.hide(); $info.show();
367
+                            $upload.text(lang.uploadStart);
368
+                            uploader.refresh();
369
+                            break;
370
+
371
+                        /* 上传中 */
372
+                        case 'uploading':
373
+                            $progress.show(); $info.hide();
374
+                            $upload.text(lang.uploadPause);
375
+                            break;
376
+
377
+                        /* 暂停上传 */
378
+                        case 'paused':
379
+                            $progress.show(); $info.hide();
380
+                            $upload.text(lang.uploadContinue);
381
+                            break;
382
+
383
+                        case 'confirm':
384
+                            $progress.show(); $info.hide();
385
+                            $upload.text(lang.uploadStart);
386
+
387
+                            stats = uploader.getStats();
388
+                            if (stats.successNum && !stats.uploadFailNum) {
389
+                                setState('finish');
390
+                                return;
391
+                            }
392
+                            break;
393
+
394
+                        case 'finish':
395
+                            $progress.hide(); $info.show();
396
+                            if (stats.uploadFailNum) {
397
+                                $upload.text(lang.uploadRetry);
398
+                            } else {
399
+                                $upload.text(lang.uploadStart);
400
+                            }
401
+                            break;
402
+                    }
403
+
404
+                    state = val;
405
+                    updateStatus();
406
+
407
+                }
408
+
409
+                if (!_this.getQueueCount()) {
410
+                    $upload.addClass('disabled')
411
+                } else {
412
+                    $upload.removeClass('disabled')
413
+                }
414
+
415
+            }
416
+
417
+            function updateStatus() {
418
+                var text = '', stats;
419
+
420
+                if (state === 'ready') {
421
+                    text = lang.updateStatusReady.replace('_', fileCount).replace('_KB', WebUploader.formatSize(fileSize));
422
+                } else if (state === 'confirm') {
423
+                    stats = uploader.getStats();
424
+                    if (stats.uploadFailNum) {
425
+                        text = lang.updateStatusConfirm.replace('_', stats.successNum).replace('_', stats.successNum);
426
+                    }
427
+                } else {
428
+                    stats = uploader.getStats();
429
+                    text = lang.updateStatusFinish.replace('_', fileCount).
430
+                        replace('_KB', WebUploader.formatSize(fileSize)).
431
+                        replace('_', stats.successNum);
432
+
433
+                    if (stats.uploadFailNum) {
434
+                        text += lang.updateStatusError.replace('_', stats.uploadFailNum);
435
+                    }
436
+                }
437
+
438
+                $info.html(text);
439
+            }
440
+
441
+            uploader.on('fileQueued', function (file) {
442
+                fileCount++;
443
+                fileSize += file.size;
444
+
445
+                if (fileCount === 1) {
446
+                    $placeHolder.addClass('element-invisible');
447
+                    $statusBar.show();
448
+                }
449
+
450
+                addFile(file);
451
+            });
452
+
453
+            uploader.on('fileDequeued', function (file) {
454
+                fileCount--;
455
+                fileSize -= file.size;
456
+
457
+                removeFile(file);
458
+                updateTotalProgress();
459
+            });
460
+
461
+            uploader.on('filesQueued', function (file) {
462
+                if (!uploader.isInProgress() && (state == 'pedding' || state == 'finish' || state == 'confirm' || state == 'ready')) {
463
+                    setState('ready');
464
+                }
465
+                updateTotalProgress();
466
+            });
467
+
468
+            uploader.on('all', function (type, files) {
469
+                switch (type) {
470
+                    case 'uploadFinished':
471
+                        setState('confirm', files);
472
+                        break;
473
+                    case 'startUpload':
474
+                        /* 添加额外的GET参数 */
475
+                        var params = utils.serializeParam(editor.queryCommandValue('serverparam')) || '',
476
+                            url = utils.formatUrl(actionUrl + (actionUrl.indexOf('?') == -1 ? '?':'&') + 'encode=utf-8&' + params);
477
+                        uploader.option('server', url);
478
+                        setState('uploading', files);
479
+                        break;
480
+                    case 'stopUpload':
481
+                        setState('paused', files);
482
+                        break;
483
+                }
484
+            });
485
+
486
+            uploader.on('uploadBeforeSend', function (file, data, header) {
487
+                //这里可以通过data对象添加POST参数
488
+                header['X_Requested_With'] = 'XMLHttpRequest';
489
+                // HaoChuan9421
490
+                if(editor.options.headers && Object.prototype.toString.apply(editor.options.headers) === "[object Object]"){
491
+                    for(var key in editor.options.headers){
492
+                        header[key] = editor.options.headers[key]
493
+                    }
494
+                }
495
+            });
496
+
497
+            uploader.on('uploadProgress', function (file, percentage) {
498
+                var $li = $('#' + file.id),
499
+                    $percent = $li.find('.progress span');
500
+
501
+                $percent.css('width', percentage * 100 + '%');
502
+                percentages[ file.id ][ 1 ] = percentage;
503
+                updateTotalProgress();
504
+            });
505
+
506
+            uploader.on('uploadSuccess', function (file, ret) {
507
+                var $file = $('#' + file.id);
508
+                try {
509
+                    var responseText = (ret._raw || ret),
510
+                        json = utils.str2json(responseText);
511
+                    if (json.state == 'SUCCESS') {
512
+                        _this.fileList.push(json);
513
+                        $file.append('<span class="success"></span>');
514
+                    } else {
515
+                        $file.find('.error').text(json.state).show();
516
+                    }
517
+                } catch (e) {
518
+                    $file.find('.error').text(lang.errorServerUpload).show();
519
+                }
520
+            });
521
+
522
+            uploader.on('uploadError', function (file, code) {
523
+            });
524
+            uploader.on('error', function (code, file) {
525
+                if (code == 'Q_TYPE_DENIED' || code == 'F_EXCEED_SIZE') {
526
+                    addFile(file);
527
+                }
528
+            });
529
+            uploader.on('uploadComplete', function (file, ret) {
530
+            });
531
+
532
+            $upload.on('click', function () {
533
+                if ($(this).hasClass('disabled')) {
534
+                    return false;
535
+                }
536
+
537
+                if (state === 'ready') {
538
+                    uploader.upload();
539
+                } else if (state === 'paused') {
540
+                    uploader.upload();
541
+                } else if (state === 'uploading') {
542
+                    uploader.stop();
543
+                }
544
+            });
545
+
546
+            $upload.addClass('state-' + state);
547
+            updateTotalProgress();
548
+        },
549
+        getQueueCount: function () {
550
+            var file, i, status, readyFile = 0, files = this.uploader.getFiles();
551
+            for (i = 0; file = files[i++]; ) {
552
+                status = file.getStatus();
553
+                if (status == 'queued' || status == 'uploading' || status == 'progress') readyFile++;
554
+            }
555
+            return readyFile;
556
+        },
557
+        getInsertList: function () {
558
+            var i, link, data, list = [],
559
+                prefix = editor.getOpt('fileUrlPrefix');
560
+            for (i = 0; i < this.fileList.length; i++) {
561
+                data = this.fileList[i];
562
+                link = data.url;
563
+                list.push({
564
+                    title: data.original || link.substr(link.lastIndexOf('/') + 1),
565
+                    url: prefix + link
566
+                });
567
+            }
568
+            return list;
569
+        }
570
+    };
571
+
572
+
573
+    /* 在线附件 */
574
+    function OnlineFile(target) {
575
+        this.container = utils.isString(target) ? document.getElementById(target) : target;
576
+        this.init();
577
+    }
578
+    OnlineFile.prototype = {
579
+        init: function () {
580
+            this.initContainer();
581
+            this.initEvents();
582
+            this.initData();
583
+        },
584
+        /* 初始化容器 */
585
+        initContainer: function () {
586
+            this.container.innerHTML = '';
587
+            this.list = document.createElement('ul');
588
+            this.clearFloat = document.createElement('li');
589
+
590
+            domUtils.addClass(this.list, 'list');
591
+            domUtils.addClass(this.clearFloat, 'clearFloat');
592
+
593
+            this.list.appendChild(this.clearFloat);
594
+            this.container.appendChild(this.list);
595
+        },
596
+        /* 初始化滚动事件,滚动到地步自动拉取数据 */
597
+        initEvents: function () {
598
+            var _this = this;
599
+
600
+            /* 滚动拉取图片 */
601
+            domUtils.on($G('fileList'), 'scroll', function(e){
602
+                var panel = this;
603
+                if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) {
604
+                    _this.getFileData();
605
+                }
606
+            });
607
+            /* 选中图片 */
608
+            domUtils.on(this.list, 'click', function (e) {
609
+                var target = e.target || e.srcElement,
610
+                    li = target.parentNode;
611
+
612
+                if (li.tagName.toLowerCase() == 'li') {
613
+                    if (domUtils.hasClass(li, 'selected')) {
614
+                        domUtils.removeClasses(li, 'selected');
615
+                    } else {
616
+                        domUtils.addClass(li, 'selected');
617
+                    }
618
+                }
619
+            });
620
+        },
621
+        /* 初始化第一次的数据 */
622
+        initData: function () {
623
+
624
+            /* 拉取数据需要使用的值 */
625
+            this.state = 0;
626
+            this.listSize = editor.getOpt('fileManagerListSize');
627
+            this.listIndex = 0;
628
+            this.listEnd = false;
629
+
630
+            /* 第一次拉取数据 */
631
+            this.getFileData();
632
+        },
633
+        /* 向后台拉取图片列表数据 */
634
+        getFileData: function () {
635
+            var _this = this;
636
+
637
+            if(!_this.listEnd && !this.isLoadingData) {
638
+                this.isLoadingData = true;
639
+                ajax.request(editor.getActionUrl(editor.getOpt('fileManagerActionName')), {
640
+                    timeout: 100000,
641
+                    data: utils.extend({
642
+                            start: this.listIndex,
643
+                            size: this.listSize
644
+                        }, editor.queryCommandValue('serverparam')),
645
+                    method: 'get',
646
+                    onsuccess: function (r) {
647
+                        try {
648
+                            var json = eval('(' + r.responseText + ')');
649
+                            if (json.state == 'SUCCESS') {
650
+                                _this.pushData(json.list);
651
+                                _this.listIndex = parseInt(json.start) + parseInt(json.list.length);
652
+                                if(_this.listIndex >= json.total) {
653
+                                    _this.listEnd = true;
654
+                                }
655
+                                _this.isLoadingData = false;
656
+                            }
657
+                        } catch (e) {
658
+                            if(r.responseText.indexOf('ue_separate_ue') != -1) {
659
+                                var list = r.responseText.split(r.responseText);
660
+                                _this.pushData(list);
661
+                                _this.listIndex = parseInt(list.length);
662
+                                _this.listEnd = true;
663
+                                _this.isLoadingData = false;
664
+                            }
665
+                        }
666
+                    },
667
+                    onerror: function () {
668
+                        _this.isLoadingData = false;
669
+                    }
670
+                });
671
+            }
672
+        },
673
+        /* 添加图片到列表界面上 */
674
+        pushData: function (list) {
675
+            var i, item, img, filetype, preview, icon, _this = this,
676
+                urlPrefix = editor.getOpt('fileManagerUrlPrefix');
677
+            for (i = 0; i < list.length; i++) {
678
+                if(list[i] && list[i].url) {
679
+                    item = document.createElement('li');
680
+                    icon = document.createElement('span');
681
+                    filetype = list[i].url.substr(list[i].url.lastIndexOf('.') + 1);
682
+
683
+                    if ( "png|jpg|jpeg|gif|bmp".indexOf(filetype) != -1 ) {
684
+                        preview = document.createElement('img');
685
+                        domUtils.on(preview, 'load', (function(image){
686
+                            return function(){
687
+                                _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight);
688
+                            };
689
+                        })(preview));
690
+                        preview.width = 113;
691
+                        preview.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) );
692
+                    } else {
693
+                        var ic = document.createElement('i'),
694
+                            textSpan = document.createElement('span');
695
+                        textSpan.innerHTML = list[i].url.substr(list[i].url.lastIndexOf('/') + 1);
696
+                        preview = document.createElement('div');
697
+                        preview.appendChild(ic);
698
+                        preview.appendChild(textSpan);
699
+                        domUtils.addClass(preview, 'file-wrapper');
700
+                        domUtils.addClass(textSpan, 'file-title');
701
+                        domUtils.addClass(ic, 'file-type-' + filetype);
702
+                        domUtils.addClass(ic, 'file-preview');
703
+                    }
704
+                    domUtils.addClass(icon, 'icon');
705
+                    item.setAttribute('data-url', urlPrefix + list[i].url);
706
+                    if (list[i].original) {
707
+                        item.setAttribute('data-title', list[i].original);
708
+                    }
709
+
710
+                    item.appendChild(preview);
711
+                    item.appendChild(icon);
712
+                    this.list.insertBefore(item, this.clearFloat);
713
+                }
714
+            }
715
+        },
716
+        /* 改变图片大小 */
717
+        scale: function (img, w, h, type) {
718
+            var ow = img.width,
719
+                oh = img.height;
720
+
721
+            if (type == 'justify') {
722
+                if (ow >= oh) {
723
+                    img.width = w;
724
+                    img.height = h * oh / ow;
725
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
726
+                } else {
727
+                    img.width = w * ow / oh;
728
+                    img.height = h;
729
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
730
+                }
731
+            } else {
732
+                if (ow >= oh) {
733
+                    img.width = w * ow / oh;
734
+                    img.height = h;
735
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
736
+                } else {
737
+                    img.width = w;
738
+                    img.height = h * oh / ow;
739
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
740
+                }
741
+            }
742
+        },
743
+        getInsertList: function () {
744
+            var i, lis = this.list.children, list = [];
745
+            for (i = 0; i < lis.length; i++) {
746
+                if (domUtils.hasClass(lis[i], 'selected')) {
747
+                    var url = lis[i].getAttribute('data-url');
748
+                    var title = lis[i].getAttribute('data-title') || url.substr(url.lastIndexOf('/') + 1);
749
+                    list.push({
750
+                        title: title,
751
+                        url: url
752
+                    });
753
+                }
754
+            }
755
+            return list;
756
+        }
757
+    };
758
+
759
+
760
+})();

二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_chm.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_default.png


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_doc.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_exe.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_jpg.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_mp3.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_mv.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_pdf.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_ppt.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_psd.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_rar.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_txt.gif


二進制
public/UEditor/dialogs/attachment/fileTypeImages/icon_xls.gif


二進制
public/UEditor/dialogs/attachment/images/alignicon.gif


二進制
public/UEditor/dialogs/attachment/images/alignicon.png


二進制
public/UEditor/dialogs/attachment/images/bg.png


二進制
public/UEditor/dialogs/attachment/images/file-icons.gif


二進制
public/UEditor/dialogs/attachment/images/file-icons.png


二進制
public/UEditor/dialogs/attachment/images/icons.gif


二進制
public/UEditor/dialogs/attachment/images/icons.png


二進制
public/UEditor/dialogs/attachment/images/image.png


二進制
public/UEditor/dialogs/attachment/images/progress.png


二進制
public/UEditor/dialogs/attachment/images/success.gif


二進制
public/UEditor/dialogs/attachment/images/success.png


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

@@ -0,0 +1,94 @@
1
+.wrapper{ width: 424px;margin: 10px auto; zoom:1;position: relative}
2
+.tabbody{height:225px;}
3
+.tabbody .panel { position: absolute;width:100%; height:100%;background: #fff; display: none;}
4
+.tabbody .focus { display: block;}
5
+
6
+body{font-size: 12px;color: #888;overflow: hidden;}
7
+input,label{vertical-align:middle}
8
+.clear{clear: both;}
9
+.pl{padding-left: 18px;padding-left: 23px\9;}
10
+
11
+#imageList {width: 420px;height: 215px;margin-top: 10px;overflow: hidden;overflow-y: auto;}
12
+#imageList div {float: left;width: 100px;height: 95px;margin: 5px 10px;}
13
+#imageList img {cursor: pointer;border: 2px solid white;}
14
+
15
+.bgarea{margin: 10px;padding: 5px;height: 84%;border: 1px solid #A8A297;}
16
+.content div{margin: 10px 0 10px 5px;}
17
+.content .iptradio{margin: 0px 5px 5px 0px;}
18
+.txt{width:280px;}
19
+
20
+.wrapcolor{height: 19px;}
21
+div.color{float: left;margin: 0;}
22
+#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;}
23
+div.alignment,#custom{margin-left: 23px;margin-left: 28px\9;}
24
+#custom input{height: 15px;min-height: 15px;width:20px;}
25
+#repeatType{width:100px;}
26
+
27
+
28
+/* 图片管理样式 */
29
+#imgManager {
30
+    width: 100%;
31
+    height: 225px;
32
+}
33
+#imgManager #imageList{
34
+    width: 100%;
35
+    overflow-x: hidden;
36
+    overflow-y: auto;
37
+}
38
+#imgManager ul {
39
+    display: block;
40
+    list-style: none;
41
+    margin: 0;
42
+    padding: 0;
43
+}
44
+#imgManager li {
45
+    float: left;
46
+    display: block;
47
+    list-style: none;
48
+    padding: 0;
49
+    width: 113px;
50
+    height: 113px;
51
+    margin: 9px 0 0 19px;
52
+    background-color: #eee;
53
+    overflow: hidden;
54
+    cursor: pointer;
55
+    position: relative;
56
+}
57
+#imgManager li.clearFloat {
58
+    float: none;
59
+    clear: both;
60
+    display: block;
61
+    width:0;
62
+    height:0;
63
+    margin: 0;
64
+    padding: 0;
65
+}
66
+#imgManager li img {
67
+    cursor: pointer;
68
+}
69
+#imgManager li .icon {
70
+    cursor: pointer;
71
+    width: 113px;
72
+    height: 113px;
73
+    position: absolute;
74
+    top: 0;
75
+    left: 0;
76
+    z-index: 2;
77
+    border: 0;
78
+    background-repeat: no-repeat;
79
+}
80
+#imgManager li .icon:hover {
81
+    width: 107px;
82
+    height: 107px;
83
+    border: 3px solid #1094fa;
84
+}
85
+#imgManager li.selected .icon {
86
+    background-image: url(images/success.png);
87
+    background-position: 75px 75px;
88
+}
89
+#imgManager li.selected .icon:hover {
90
+    width: 107px;
91
+    height: 107px;
92
+    border: 3px solid #1094fa;
93
+    background-position: 72px 72px;
94
+}

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

@@ -0,0 +1,56 @@
1
+<!DOCTYPE HTML>
2
+<html>
3
+<head>
4
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
5
+    <script type="text/javascript" src="../internal.js"></script>
6
+    <link rel="stylesheet" type="text/css" href="background.css">
7
+</head>
8
+<body>
9
+    <div id="bg_container" class="wrapper">
10
+        <div id="tabHeads" class="tabhead">
11
+            <span class="focus" data-content-id="normal"><var id="lang_background_normal"></var></span>
12
+            <span class="" data-content-id="imgManager"><var id="lang_background_local"></var></span>
13
+        </div>
14
+        <div id="tabBodys" class="tabbody">
15
+            <div id="normal" class="panel focus">
16
+                <fieldset class="bgarea">
17
+                    <legend><var id="lang_background_set"></var></legend>
18
+                    <div class="content">
19
+                        <div>
20
+                            <label><input id="nocolorRadio" class="iptradio" type="radio" name="t" value="none" checked="checked"><var id="lang_background_none"></var></label>
21
+                            <label><input id="coloredRadio" class="iptradio" type="radio" name="t" value="color"><var id="lang_background_colored"></var></label>
22
+                        </div>
23
+                        <div class="wrapcolor pl">
24
+                            <div class="color">
25
+                                <var id="lang_background_color"></var>:
26
+                            </div>
27
+                            <div id="colorPicker"></div>
28
+                            <div class="clear"></div>
29
+                        </div>
30
+                        <div class="wrapcolor pl">
31
+                            <label><var id="lang_background_netimg"></var>:</label><input class="txt" type="text" id="url">
32
+                        </div>
33
+                        <div id="alignment" class="alignment">
34
+                            <var id="lang_background_align"></var>:<select id="repeatType">
35
+                                <option value="center"></option>
36
+                                <option value="repeat-x"></option>
37
+                                <option value="repeat-y"></option>
38
+                                <option value="repeat"></option>
39
+                                <option value="self"></option>
40
+                            </select>
41
+                        </div>
42
+                        <div id="custom" >
43
+                            <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
44
+                        </div>
45
+                    </div>
46
+                </fieldset>
47
+
48
+            </div>
49
+            <div id="imgManager" class="panel">
50
+                <div id="imageList" style=""></div>
51
+            </div>
52
+        </div>
53
+    </div>
54
+    <script type="text/javascript" src="background.js"></script>
55
+</body>
56
+</html>

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

@@ -0,0 +1,376 @@
1
+(function () {
2
+
3
+    var onlineImage,
4
+        backupStyle = editor.queryCommandValue('background');
5
+
6
+    window.onload = function () {
7
+        initTabs();
8
+        initColorSelector();
9
+    };
10
+
11
+    /* 初始化tab标签 */
12
+    function initTabs(){
13
+        var tabs = $G('tabHeads').children;
14
+        for (var i = 0; i < tabs.length; i++) {
15
+            domUtils.on(tabs[i], "click", function (e) {
16
+                var target = e.target || e.srcElement;
17
+                for (var j = 0; j < tabs.length; j++) {
18
+                    if(tabs[j] == target){
19
+                        tabs[j].className = "focus";
20
+                        var contentId = tabs[j].getAttribute('data-content-id');
21
+                        $G(contentId).style.display = "block";
22
+                        if(contentId == 'imgManager') {
23
+                            initImagePanel();
24
+                        }
25
+                    }else {
26
+                        tabs[j].className = "";
27
+                        $G(tabs[j].getAttribute('data-content-id')).style.display = "none";
28
+                    }
29
+                }
30
+            });
31
+        }
32
+    }
33
+
34
+    /* 初始化颜色设置 */
35
+    function initColorSelector () {
36
+        var obj = editor.queryCommandValue('background');
37
+        if (obj) {
38
+            var color = obj['background-color'],
39
+                repeat = obj['background-repeat'] || 'repeat',
40
+                image = obj['background-image'] || '',
41
+                position = obj['background-position'] || 'center center',
42
+                pos = position.split(' '),
43
+                x = parseInt(pos[0]) || 0,
44
+                y = parseInt(pos[1]) || 0;
45
+
46
+            if(repeat == 'no-repeat' && (x || y)) repeat = 'self';
47
+
48
+            image = image.match(/url[\s]*\(([^\)]*)\)/);
49
+            image = image ? image[1]:'';
50
+            updateFormState('colored', color, image, repeat, x, y);
51
+        } else {
52
+            updateFormState();
53
+        }
54
+
55
+        var updateHandler = function () {
56
+            updateFormState();
57
+            updateBackground();
58
+        }
59
+        domUtils.on($G('nocolorRadio'), 'click', updateBackground);
60
+        domUtils.on($G('coloredRadio'), 'click', updateHandler);
61
+        domUtils.on($G('url'), 'keyup', function(){
62
+            if($G('url').value && $G('alignment').style.display == "none") {
63
+                utils.each($G('repeatType').children, function(item){
64
+                    item.selected = ('repeat' == item.getAttribute('value') ? 'selected':false);
65
+                });
66
+            }
67
+            updateHandler();
68
+        });
69
+        domUtils.on($G('repeatType'), 'change', updateHandler);
70
+        domUtils.on($G('x'), 'keyup', updateBackground);
71
+        domUtils.on($G('y'), 'keyup', updateBackground);
72
+
73
+        initColorPicker();
74
+    }
75
+
76
+    /* 初始化颜色选择器 */
77
+    function initColorPicker() {
78
+        var me = editor,
79
+            cp = $G("colorPicker");
80
+
81
+        /* 生成颜色选择器ui对象 */
82
+        var popup = new UE.ui.Popup({
83
+            content: new UE.ui.ColorPicker({
84
+                noColorText: me.getLang("clearColor"),
85
+                editor: me,
86
+                onpickcolor: function (t, color) {
87
+                    updateFormState('colored', color);
88
+                    updateBackground();
89
+                    UE.ui.Popup.postHide();
90
+                },
91
+                onpicknocolor: function (t, color) {
92
+                    updateFormState('colored', 'transparent');
93
+                    updateBackground();
94
+                    UE.ui.Popup.postHide();
95
+                }
96
+            }),
97
+            editor: me,
98
+            onhide: function () {
99
+            }
100
+        });
101
+
102
+        /* 设置颜色选择器 */
103
+        domUtils.on(cp, "click", function () {
104
+            popup.showAnchor(this);
105
+        });
106
+        domUtils.on(document, 'mousedown', function (evt) {
107
+            var el = evt.target || evt.srcElement;
108
+            UE.ui.Popup.postHide(el);
109
+        });
110
+        domUtils.on(window, 'scroll', function () {
111
+            UE.ui.Popup.postHide();
112
+        });
113
+    }
114
+
115
+    /* 初始化在线图片列表 */
116
+    function initImagePanel() {
117
+        onlineImage = onlineImage || new OnlineImage('imageList');
118
+    }
119
+
120
+    /* 更新背景色设置面板 */
121
+    function updateFormState (radio, color, url, align, x, y) {
122
+        var nocolorRadio = $G('nocolorRadio'),
123
+            coloredRadio = $G('coloredRadio');
124
+
125
+        if(radio) {
126
+            nocolorRadio.checked = (radio == 'colored' ? false:'checked');
127
+            coloredRadio.checked = (radio == 'colored' ? 'checked':false);
128
+        }
129
+        if(color) {
130
+            domUtils.setStyle($G("colorPicker"), "background-color", color);
131
+        }
132
+
133
+        if(url && /^\//.test(url)) {
134
+            var a = document.createElement('a');
135
+            a.href = url;
136
+            browser.ie && (a.href = a.href);
137
+            url = browser.ie ? a.href:(a.protocol + '//' + a.host + a.pathname + a.search + a.hash);
138
+        }
139
+
140
+        if(url || url === '') {
141
+            $G('url').value = url;
142
+        }
143
+        if(align) {
144
+            utils.each($G('repeatType').children, function(item){
145
+                item.selected = (align == item.getAttribute('value') ? 'selected':false);
146
+            });
147
+        }
148
+        if(x || y) {
149
+            $G('x').value = parseInt(x) || 0;
150
+            $G('y').value = parseInt(y) || 0;
151
+        }
152
+
153
+        $G('alignment').style.display = coloredRadio.checked && $G('url').value ? '':'none';
154
+        $G('custom').style.display = coloredRadio.checked && $G('url').value && $G('repeatType').value == 'self' ? '':'none';
155
+    }
156
+
157
+    /* 更新背景颜色 */
158
+    function updateBackground () {
159
+        if ($G('coloredRadio').checked) {
160
+            var color = domUtils.getStyle($G("colorPicker"), "background-color"),
161
+                bgimg = $G("url").value,
162
+                align = $G("repeatType").value,
163
+                backgroundObj = {
164
+                    "background-repeat": "no-repeat",
165
+                    "background-position": "center center"
166
+                };
167
+
168
+            if (color) backgroundObj["background-color"] = color;
169
+            if (bgimg) backgroundObj["background-image"] = 'url(' + bgimg + ')';
170
+            if (align == 'self') {
171
+                backgroundObj["background-position"] = $G("x").value + "px " + $G("y").value + "px";
172
+            } else if (align == 'repeat-x' || align == 'repeat-y' || align == 'repeat') {
173
+                backgroundObj["background-repeat"] = align;
174
+            }
175
+
176
+            editor.execCommand('background', backgroundObj);
177
+        } else {
178
+            editor.execCommand('background', null);
179
+        }
180
+    }
181
+
182
+
183
+    /* 在线图片 */
184
+    function OnlineImage(target) {
185
+        this.container = utils.isString(target) ? document.getElementById(target) : target;
186
+        this.init();
187
+    }
188
+    OnlineImage.prototype = {
189
+        init: function () {
190
+            this.reset();
191
+            this.initEvents();
192
+        },
193
+        /* 初始化容器 */
194
+        initContainer: function () {
195
+            this.container.innerHTML = '';
196
+            this.list = document.createElement('ul');
197
+            this.clearFloat = document.createElement('li');
198
+
199
+            domUtils.addClass(this.list, 'list');
200
+            domUtils.addClass(this.clearFloat, 'clearFloat');
201
+
202
+            this.list.id = 'imageListUl';
203
+            this.list.appendChild(this.clearFloat);
204
+            this.container.appendChild(this.list);
205
+        },
206
+        /* 初始化滚动事件,滚动到地步自动拉取数据 */
207
+        initEvents: function () {
208
+            var _this = this;
209
+
210
+            /* 滚动拉取图片 */
211
+            domUtils.on($G('imageList'), 'scroll', function(e){
212
+                var panel = this;
213
+                if (panel.scrollHeight - (panel.offsetHeight + panel.scrollTop) < 10) {
214
+                    _this.getImageData();
215
+                }
216
+            });
217
+            /* 选中图片 */
218
+            domUtils.on(this.container, 'click', function (e) {
219
+                var target = e.target || e.srcElement,
220
+                    li = target.parentNode,
221
+                    nodes = $G('imageListUl').childNodes;
222
+
223
+                if (li.tagName.toLowerCase() == 'li') {
224
+                    updateFormState('nocolor', null, '');
225
+                    for (var i = 0, node; node = nodes[i++];) {
226
+                        if (node == li && !domUtils.hasClass(node, 'selected')) {
227
+                            domUtils.addClass(node, 'selected');
228
+                            updateFormState('colored', null, li.firstChild.getAttribute("_src"), 'repeat');
229
+                        } else {
230
+                            domUtils.removeClasses(node, 'selected');
231
+                        }
232
+                    }
233
+                    updateBackground();
234
+                }
235
+            });
236
+        },
237
+        /* 初始化第一次的数据 */
238
+        initData: function () {
239
+
240
+            /* 拉取数据需要使用的值 */
241
+            this.state = 0;
242
+            this.listSize = editor.getOpt('imageManagerListSize');
243
+            this.listIndex = 0;
244
+            this.listEnd = false;
245
+
246
+            /* 第一次拉取数据 */
247
+            this.getImageData();
248
+        },
249
+        /* 重置界面 */
250
+        reset: function() {
251
+            this.initContainer();
252
+            this.initData();
253
+        },
254
+        /* 向后台拉取图片列表数据 */
255
+        getImageData: function () {
256
+            var _this = this;
257
+
258
+            if(!_this.listEnd && !this.isLoadingData) {
259
+                this.isLoadingData = true;
260
+                var url = editor.getActionUrl(editor.getOpt('imageManagerActionName')),
261
+                    isJsonp = utils.isCrossDomainUrl(url);
262
+                ajax.request(url, {
263
+                    'timeout': 100000,
264
+                    'dataType': isJsonp ? 'jsonp':'',
265
+                    'data': utils.extend({
266
+                            start: this.listIndex,
267
+                            size: this.listSize
268
+                        }, editor.queryCommandValue('serverparam')),
269
+                    'method': 'get',
270
+                    'onsuccess': function (r) {
271
+                        try {
272
+                            var json = isJsonp ? r:eval('(' + r.responseText + ')');
273
+                            if (json.state == 'SUCCESS') {
274
+                                _this.pushData(json.list);
275
+                                _this.listIndex = parseInt(json.start) + parseInt(json.list.length);
276
+                                if(_this.listIndex >= json.total) {
277
+                                    _this.listEnd = true;
278
+                                }
279
+                                _this.isLoadingData = false;
280
+                            }
281
+                        } catch (e) {
282
+                            if(r.responseText.indexOf('ue_separate_ue') != -1) {
283
+                                var list = r.responseText.split(r.responseText);
284
+                                _this.pushData(list);
285
+                                _this.listIndex = parseInt(list.length);
286
+                                _this.listEnd = true;
287
+                                _this.isLoadingData = false;
288
+                            }
289
+                        }
290
+                    },
291
+                    'onerror': function () {
292
+                        _this.isLoadingData = false;
293
+                    }
294
+                });
295
+            }
296
+        },
297
+        /* 添加图片到列表界面上 */
298
+        pushData: function (list) {
299
+            var i, item, img, icon, _this = this,
300
+                urlPrefix = editor.getOpt('imageManagerUrlPrefix');
301
+            for (i = 0; i < list.length; i++) {
302
+                if(list[i] && list[i].url) {
303
+                    item = document.createElement('li');
304
+                    img = document.createElement('img');
305
+                    icon = document.createElement('span');
306
+
307
+                    domUtils.on(img, 'load', (function(image){
308
+                        return function(){
309
+                            _this.scale(image, image.parentNode.offsetWidth, image.parentNode.offsetHeight);
310
+                        }
311
+                    })(img));
312
+                    img.width = 113;
313
+                    img.setAttribute('src', urlPrefix + list[i].url + (list[i].url.indexOf('?') == -1 ? '?noCache=':'&noCache=') + (+new Date()).toString(36) );
314
+                    img.setAttribute('_src', urlPrefix + list[i].url);
315
+                    domUtils.addClass(icon, 'icon');
316
+
317
+                    item.appendChild(img);
318
+                    item.appendChild(icon);
319
+                    this.list.insertBefore(item, this.clearFloat);
320
+                }
321
+            }
322
+        },
323
+        /* 改变图片大小 */
324
+        scale: function (img, w, h, type) {
325
+            var ow = img.width,
326
+                oh = img.height;
327
+
328
+            if (type == 'justify') {
329
+                if (ow >= oh) {
330
+                    img.width = w;
331
+                    img.height = h * oh / ow;
332
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
333
+                } else {
334
+                    img.width = w * ow / oh;
335
+                    img.height = h;
336
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
337
+                }
338
+            } else {
339
+                if (ow >= oh) {
340
+                    img.width = w * ow / oh;
341
+                    img.height = h;
342
+                    img.style.marginLeft = '-' + parseInt((img.width - w) / 2) + 'px';
343
+                } else {
344
+                    img.width = w;
345
+                    img.height = h * oh / ow;
346
+                    img.style.marginTop = '-' + parseInt((img.height - h) / 2) + 'px';
347
+                }
348
+            }
349
+        },
350
+        getInsertList: function () {
351
+            var i, lis = this.list.children, list = [], align = getAlign();
352
+            for (i = 0; i < lis.length; i++) {
353
+                if (domUtils.hasClass(lis[i], 'selected')) {
354
+                    var img = lis[i].firstChild,
355
+                        src = img.getAttribute('_src');
356
+                    list.push({
357
+                        src: src,
358
+                        _src: src,
359
+                        floatStyle: align
360
+                    });
361
+                }
362
+
363
+            }
364
+            return list;
365
+        }
366
+    };
367
+
368
+    dialog.onok = function () {
369
+        updateBackground();
370
+        editor.fireEvent('saveScene');
371
+    };
372
+    dialog.oncancel = function () {
373
+        editor.execCommand('background', backupStyle);
374
+    };
375
+
376
+})();

二進制
public/UEditor/dialogs/background/images/bg.png


二進制
public/UEditor/dialogs/background/images/success.png


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

@@ -0,0 +1,65 @@
1
+/*
2
+ * 图表配置文件
3
+ * */
4
+
5
+
6
+//不同类型的配置
7
+var typeConfig = [
8
+    {
9
+        chart: {
10
+            type: 'line'
11
+        },
12
+        plotOptions: {
13
+            line: {
14
+                dataLabels: {
15
+                    enabled: false
16
+                },
17
+                enableMouseTracking: true
18
+            }
19
+        }
20
+    }, {
21
+        chart: {
22
+            type: 'line'
23
+        },
24
+        plotOptions: {
25
+            line: {
26
+                dataLabels: {
27
+                    enabled: true
28
+                },
29
+                enableMouseTracking: false
30
+            }
31
+        }
32
+    }, {
33
+        chart: {
34
+            type: 'area'
35
+        }
36
+    }, {
37
+        chart: {
38
+            type: 'bar'
39
+        }
40
+    }, {
41
+        chart: {
42
+            type: 'column'
43
+        }
44
+    }, {
45
+        chart: {
46
+            plotBackgroundColor: null,
47
+            plotBorderWidth: null,
48
+            plotShadow: false
49
+        },
50
+        plotOptions: {
51
+            pie: {
52
+                allowPointSelect: true,
53
+                cursor: 'pointer',
54
+                dataLabels: {
55
+                    enabled: true,
56
+                    color: '#000000',
57
+                    connectorColor: '#000000',
58
+                    formatter: function() {
59
+                        return '<b>'+ this.point.name +'</b>: '+ ( Math.round( this.point.percentage*100 ) / 100 ) +' %';
60
+                    }
61
+                }
62
+            }
63
+        }
64
+    }
65
+];

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

@@ -0,0 +1,165 @@
1
+html, body {
2
+    width: 100%;
3
+    height: 100%;
4
+    margin: 0;
5
+    padding: 0;
6
+    overflow-x: hidden;
7
+}
8
+
9
+.main {
10
+    width: 100%;
11
+    overflow: hidden;
12
+}
13
+
14
+.table-view {
15
+    height: 100%;
16
+    float: left;
17
+    margin: 20px;
18
+    width: 40%;
19
+}
20
+
21
+.table-view .table-container {
22
+    width: 100%;
23
+    margin-bottom: 50px;
24
+    overflow: scroll;
25
+}
26
+
27
+.table-view th {
28
+    padding: 5px 10px;
29
+    background-color: #F7F7F7;
30
+}
31
+
32
+.table-view td {
33
+    width: 50px;
34
+    text-align: center;
35
+    padding:0;
36
+}
37
+
38
+.table-container input {
39
+    width: 40px;
40
+    padding: 5px;
41
+    border: none;
42
+    outline: none;
43
+}
44
+
45
+.table-view caption {
46
+    font-size: 18px;
47
+    text-align: left;
48
+}
49
+
50
+.charts-view {
51
+    /*margin-left: 49%!important;*/
52
+    width: 50%;
53
+    margin-left: 49%;
54
+    height: 400px;
55
+}
56
+
57
+.charts-container {
58
+    border-left: 1px solid #c3c3c3;
59
+}
60
+
61
+.charts-format fieldset {
62
+    padding-left: 20px;
63
+    margin-bottom: 50px;
64
+}
65
+
66
+.charts-format legend {
67
+    padding-left: 10px;
68
+    padding-right: 10px;
69
+}
70
+
71
+.format-item-container {
72
+    padding: 20px;
73
+}
74
+
75
+.format-item-container label {
76
+    display: block;
77
+    margin: 10px 0;
78
+}
79
+
80
+.charts-format .data-item {
81
+    border: 1px solid black;
82
+    outline: none;
83
+    padding: 2px 3px;
84
+}
85
+
86
+/* 图表类型 */
87
+
88
+.charts-type {
89
+    margin-top: 50px;
90
+    height: 300px;
91
+}
92
+
93
+.scroll-view {
94
+    border: 1px solid #c3c3c3;
95
+    border-left: none;
96
+    border-right: none;
97
+    overflow: hidden;
98
+}
99
+
100
+.scroll-container {
101
+    margin: 20px;
102
+    width: 100%;
103
+    overflow: hidden;
104
+}
105
+
106
+.scroll-bed {
107
+    width: 10000px;
108
+    _margin-top: 20px;
109
+    -webkit-transition: margin-left .5s ease;
110
+    -moz-transition: margin-left .5s ease;
111
+    transition: margin-left .5s ease;
112
+}
113
+
114
+.view-box {
115
+    display: inline-block;
116
+    *display: inline;
117
+    *zoom: 1;
118
+    margin-right: 20px;
119
+    border: 2px solid white;
120
+    line-height: 0;
121
+    overflow: hidden;
122
+    cursor: pointer;
123
+}
124
+
125
+.view-box img {
126
+    border: 1px solid #cecece;
127
+}
128
+
129
+.view-box.selected {
130
+    border-color: #7274A7;
131
+}
132
+
133
+.button-container {
134
+    margin-bottom: 20px;
135
+    text-align: center;
136
+}
137
+
138
+.button-container a {
139
+    display: inline-block;
140
+    width: 100px;
141
+    height: 25px;
142
+    line-height: 25px;
143
+    border: 1px solid #c2ccd1;
144
+    margin-right: 30px;
145
+    text-decoration: none;
146
+    color: black;
147
+    -webkit-border-radius: 2px;
148
+    -moz-border-radius: 2px;
149
+    border-radius: 2px;
150
+}
151
+
152
+.button-container a:HOVER {
153
+    background: #fcfcfc;
154
+}
155
+
156
+.button-container a:ACTIVE {
157
+    border-top-color: #c2ccd1;
158
+    box-shadow:inset 0 5px 4px -4px rgba(49, 49, 64, 0.1);
159
+}
160
+
161
+.edui-charts-not-data {
162
+    height: 100px;
163
+    line-height: 100px;
164
+    text-align: center;
165
+}

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

@@ -0,0 +1,89 @@
1
+<!DOCTYPE html>
2
+<html>
3
+    <head>
4
+        <title>chart</title>
5
+        <meta chartset="utf-8">
6
+        <link rel="stylesheet" type="text/css" href="charts.css">
7
+        <script type="text/javascript" src="../internal.js"></script>
8
+    </head>
9
+    <body>
10
+        <div class="main">
11
+            <div class="table-view">
12
+                <h3><var id="lang_data_source"></var></h3>
13
+                <div id="tableContainer" class="table-container"></div>
14
+                <h3><var id="lang_chart_format"></var></h3>
15
+                <form name="data-form">
16
+                    <div class="charts-format">
17
+                        <fieldset>
18
+                            <legend><var id="lang_data_align"></var></legend>
19
+                            <div class="format-item-container">
20
+                                <label>
21
+                                    <input type="radio" class="format-ctrl not-pie-item" name="charts-format" value="1" checked="checked">
22
+                                    <var id="lang_chart_align_same"></var>
23
+                                </label>
24
+                                <label>
25
+                                    <input type="radio" class="format-ctrl not-pie-item" name="charts-format" value="-1">
26
+                                    <var id="lang_chart_align_reverse"></var>
27
+                                </label>
28
+                                <br>
29
+                            </div>
30
+                        </fieldset>
31
+                        <fieldset>
32
+                            <legend><var id="lang_chart_title"></var></legend>
33
+                            <div class="format-item-container">
34
+                                <label>
35
+                                    <var id="lang_chart_main_title"></var><input type="text" name="title" class="data-item">
36
+                                </label>
37
+                                <label>
38
+                                    <var id="lang_chart_sub_title"></var><input type="text" name="sub-title" class="data-item not-pie-item">
39
+                                </label>
40
+                                <label>
41
+                                    <var id="lang_chart_x_title"></var><input type="text" name="x-title" class="data-item not-pie-item">
42
+                                </label>
43
+                                <label>
44
+                                    <var id="lang_chart_y_title"></var><input type="text" name="y-title" class="data-item not-pie-item">
45
+                                </label>
46
+                            </div>
47
+                        </fieldset>
48
+                        <fieldset>
49
+                            <legend><var id="lang_chart_tip"></var></legend>
50
+                            <div class="format-item-container">
51
+                                <label>
52
+                                    <var id="lang_cahrt_tip_prefix"></var>
53
+                                    <input type="text" id="tipInput" name="tip" class="data-item" disabled="disabled">
54
+                                </label>
55
+                                <p><var id="lang_cahrt_tip_description"></var></p>
56
+                            </div>
57
+                        </fieldset>
58
+                        <fieldset>
59
+                            <legend><var id="lang_chart_data_unit"></var></legend>
60
+                            <div class="format-item-container">
61
+                                <label><var id="lang_chart_data_unit_title"></var><input type="text" name="unit" class="data-item"></label>
62
+                                <p><var id="lang_chart_data_unit_description"></var></p>
63
+                            </div>
64
+                        </fieldset>
65
+                    </div>
66
+                </form>
67
+            </div>
68
+            <div class="charts-view">
69
+                <div id="chartsContainer" class="charts-container"></div>
70
+                <div id="chartsType" class="charts-type">
71
+                    <h3><var id="lang_chart_type"></var></h3>
72
+                    <div class="scroll-view">
73
+                        <div class="scroll-container">
74
+                            <div id="scrollBed" class="scroll-bed"></div>
75
+                        </div>
76
+                        <div id="buttonContainer" class="button-container">
77
+                            <a href="#" data-title="prev"><var id="lang_prev_btn"></var></a>
78
+                            <a href="#" data-title="next"><var id="lang_next_btn"></var></a>
79
+                        </div>
80
+                    </div>
81
+                </div>
82
+            </div>
83
+        </div>
84
+        <script src="../../third-party/jquery-1.10.2.min.js"></script>
85
+        <script src="../../third-party/highcharts/highcharts.js"></script>
86
+        <script src="chart.config.js"></script>
87
+        <script src="charts.js"></script>
88
+    </body>
89
+</html>

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

@@ -0,0 +1,519 @@
1
+/*
2
+ * 图片转换对话框脚本
3
+ **/
4
+
5
+var tableData = [],
6
+    //编辑器页面table
7
+    editorTable = null,
8
+    chartsConfig = window.typeConfig,
9
+    resizeTimer = null,
10
+    //初始默认图表类型
11
+    currentChartType = 0;
12
+
13
+window.onload = function () {
14
+
15
+    editorTable = domUtils.findParentByTagName( editor.selection.getRange().startContainer, 'table', true);
16
+
17
+    //未找到表格, 显示错误页面
18
+    if ( !editorTable ) {
19
+        document.body.innerHTML = "<div class='edui-charts-not-data'>未找到数据</div>";
20
+        return;
21
+    }
22
+
23
+    //初始化图表类型选择
24
+    initChartsTypeView();
25
+    renderTable( editorTable );
26
+    initEvent();
27
+    initUserConfig( editorTable.getAttribute( "data-chart" ) );
28
+    $( "#scrollBed .view-box:eq("+ currentChartType +")" ).trigger( "click" );
29
+    updateViewType( currentChartType );
30
+
31
+    dialog.addListener( "resize", function () {
32
+
33
+        if ( resizeTimer != null ) {
34
+            window.clearTimeout( resizeTimer );
35
+        }
36
+
37
+        resizeTimer = window.setTimeout( function () {
38
+
39
+            resizeTimer = null;
40
+
41
+            renderCharts();
42
+
43
+        }, 500 );
44
+
45
+    } );
46
+
47
+};
48
+
49
+function initChartsTypeView () {
50
+
51
+    var contents = [];
52
+
53
+    for ( var i = 0, len = chartsConfig.length; i<len; i++ ) {
54
+
55
+        contents.push( '<div class="view-box" data-chart-type="'+ i +'"><img width="300" src="images/charts'+ i +'.png"></div>' );
56
+
57
+    }
58
+
59
+    $( "#scrollBed" ).html( contents.join( "" ) );
60
+
61
+}
62
+
63
+//渲染table, 以便用户修改数据
64
+function renderTable ( table ) {
65
+
66
+    var tableHtml = [];
67
+
68
+    //构造数据
69
+    for ( var i = 0, row; row = table.rows[ i ]; i++ ) {
70
+
71
+        tableData[ i ] = [];
72
+        tableHtml[ i ] = [];
73
+
74
+        for ( var j = 0, cell; cell = row.cells[ j ]; j++ ) {
75
+
76
+            var value = getCellValue( cell );
77
+
78
+            if ( i > 0 && j > 0 ) {
79
+                value = +value;
80
+            }
81
+
82
+            if ( i === 0 || j === 0 ) {
83
+                tableHtml[ i ].push( '<th>'+ value +'</th>' );
84
+            } else {
85
+                tableHtml[ i ].push( '<td><input type="text" class="data-item" value="'+ value +'"></td>' );
86
+            }
87
+
88
+            tableData[ i ][ j ] = value;
89
+
90
+        }
91
+
92
+        tableHtml[ i ] = tableHtml[ i ].join( "" );
93
+
94
+    }
95
+
96
+    //draw 表格
97
+    $( "#tableContainer" ).html( '<table id="showTable" border="1"><tbody><tr>'+ tableHtml.join( "</tr><tr>" ) +'</tr></tbody></table>' );
98
+
99
+}
100
+
101
+/*
102
+ * 根据表格已有的图表属性初始化当前图表属性
103
+ */
104
+function initUserConfig ( config ) {
105
+
106
+    var parsedConfig = {};
107
+
108
+    if ( !config ) {
109
+        return;
110
+    }
111
+
112
+    config = config.split( ";" );
113
+
114
+    $.each( config, function ( index, item ) {
115
+
116
+        item = item.split( ":" );
117
+        parsedConfig[ item[ 0 ] ] = item[ 1 ];
118
+
119
+    } );
120
+
121
+    setUserConfig( parsedConfig );
122
+
123
+}
124
+
125
+function initEvent () {
126
+
127
+    var cacheValue = null,
128
+        //图表类型数
129
+        typeViewCount = chartsConfig.length- 1,
130
+        $chartsTypeViewBox = $( '#scrollBed .view-box' );
131
+
132
+    $( ".charts-format" ).delegate( ".format-ctrl", "change", function () {
133
+
134
+        renderCharts();
135
+
136
+    } )
137
+
138
+    $( ".table-view" ).delegate( ".data-item", "focus", function () {
139
+
140
+        cacheValue = this.value;
141
+
142
+    } ).delegate( ".data-item", "blur", function () {
143
+
144
+        if ( this.value !== cacheValue ) {
145
+            renderCharts();
146
+        }
147
+
148
+        cacheValue = null;
149
+
150
+    } );
151
+
152
+    $( "#buttonContainer" ).delegate( "a", "click", function (e) {
153
+
154
+        e.preventDefault();
155
+
156
+        if ( this.getAttribute( "data-title" ) === 'prev' ) {
157
+
158
+            if ( currentChartType > 0 ) {
159
+                currentChartType--;
160
+                updateViewType( currentChartType );
161
+            }
162
+
163
+        } else {
164
+
165
+            if ( currentChartType < typeViewCount ) {
166
+                currentChartType++;
167
+                updateViewType( currentChartType );
168
+            }
169
+
170
+        }
171
+
172
+    } );
173
+
174
+    //图表类型变化
175
+    $( '#scrollBed' ).delegate( ".view-box", "click", function (e) {
176
+
177
+        var index = $( this ).attr( "data-chart-type" );
178
+        $chartsTypeViewBox.removeClass( "selected" );
179
+        $( $chartsTypeViewBox[ index ] ).addClass( "selected" );
180
+
181
+        currentChartType = index | 0;
182
+
183
+        //饼图, 禁用部分配置
184
+        if ( currentChartType === chartsConfig.length - 1 ) {
185
+
186
+            disableNotPieConfig();
187
+
188
+        //启用完整配置
189
+        } else {
190
+
191
+            enableNotPieConfig();
192
+
193
+        }
194
+
195
+        renderCharts();
196
+
197
+    } );
198
+
199
+}
200
+
201
+function renderCharts () {
202
+
203
+    var data = collectData();
204
+
205
+    $('#chartsContainer').highcharts( $.extend( {}, chartsConfig[ currentChartType ], {
206
+
207
+        credits: {
208
+            enabled: false
209
+        },
210
+        exporting: {
211
+            enabled: false
212
+        },
213
+        title: {
214
+            text: data.title,
215
+            x: -20 //center
216
+        },
217
+        subtitle: {
218
+            text: data.subTitle,
219
+            x: -20
220
+        },
221
+        xAxis: {
222
+            title: {
223
+                text: data.xTitle
224
+            },
225
+            categories: data.categories
226
+        },
227
+        yAxis: {
228
+            title: {
229
+                text: data.yTitle
230
+            },
231
+            plotLines: [{
232
+                value: 0,
233
+                width: 1,
234
+                color: '#808080'
235
+            }]
236
+        },
237
+        tooltip: {
238
+            enabled: true,
239
+            valueSuffix: data.suffix
240
+        },
241
+        legend: {
242
+            layout: 'vertical',
243
+            align: 'right',
244
+            verticalAlign: 'middle',
245
+            borderWidth: 1
246
+        },
247
+        series: data.series
248
+
249
+    } ));
250
+
251
+}
252
+
253
+function updateViewType ( index ) {
254
+
255
+    $( "#scrollBed" ).css( 'marginLeft', -index*324+'px' );
256
+
257
+}
258
+
259
+function collectData () {
260
+
261
+    var form = document.forms[ 'data-form' ],
262
+        data = null;
263
+
264
+    if ( currentChartType !== chartsConfig.length - 1 ) {
265
+
266
+        data = getSeriesAndCategories();
267
+        $.extend( data, getUserConfig() );
268
+
269
+    //饼图数据格式
270
+    } else {
271
+        data = getSeriesForPieChart();
272
+        data.title = form[ 'title' ].value;
273
+        data.suffix = form[ 'unit' ].value;
274
+    }
275
+
276
+    return data;
277
+
278
+}
279
+
280
+/**
281
+ * 获取用户配置信息
282
+ */
283
+function getUserConfig () {
284
+
285
+    var form = document.forms[ 'data-form' ],
286
+        info = {
287
+            title: form[ 'title' ].value,
288
+            subTitle: form[ 'sub-title' ].value,
289
+            xTitle: form[ 'x-title' ].value,
290
+            yTitle: form[ 'y-title' ].value,
291
+            suffix: form[ 'unit' ].value,
292
+            //数据对齐方式
293
+            tableDataFormat: getTableDataFormat (),
294
+            //饼图提示文字
295
+            tip: $( "#tipInput" ).val()
296
+        };
297
+
298
+    return info;
299
+
300
+}
301
+
302
+function setUserConfig ( config ) {
303
+
304
+    var form = document.forms[ 'data-form' ];
305
+
306
+    config.title && ( form[ 'title' ].value = config.title );
307
+    config.subTitle && ( form[ 'sub-title' ].value = config.subTitle );
308
+    config.xTitle && ( form[ 'x-title' ].value = config.xTitle );
309
+    config.yTitle && ( form[ 'y-title' ].value = config.yTitle );
310
+    config.suffix && ( form[ 'unit' ].value = config.suffix );
311
+    config.dataFormat == "-1" && ( form[ 'charts-format' ][ 1 ].checked = true );
312
+    config.tip && ( form[ 'tip' ].value = config.tip );
313
+    currentChartType = config.chartType || 0;
314
+
315
+}
316
+
317
+function getSeriesAndCategories () {
318
+
319
+    var form = document.forms[ 'data-form' ],
320
+        series = [],
321
+        categories = [],
322
+        tmp = [],
323
+        tableData = getTableData();
324
+
325
+    //反转数据
326
+    if ( getTableDataFormat() === "-1" ) {
327
+
328
+        for ( var i = 0, len = tableData.length; i < len; i++ ) {
329
+
330
+            for ( var j = 0, jlen = tableData[ i ].length; j < jlen; j++ ) {
331
+
332
+                if ( !tmp[ j ] ) {
333
+                    tmp[ j ] = [];
334
+                }
335
+
336
+                tmp[ j ][ i ] = tableData[ i ][ j ];
337
+
338
+            }
339
+
340
+        }
341
+
342
+        tableData = tmp;
343
+
344
+    }
345
+
346
+    categories = tableData[0].slice( 1 );
347
+
348
+    for ( var i = 1, data; data = tableData[ i ]; i++ ) {
349
+
350
+        series.push( {
351
+            name: data[ 0 ],
352
+            data: data.slice( 1 )
353
+        } );
354
+
355
+    }
356
+
357
+    return {
358
+        series: series,
359
+        categories: categories
360
+    };
361
+
362
+}
363
+
364
+/*
365
+ * 获取数据源数据对齐方式
366
+ */
367
+function getTableDataFormat () {
368
+
369
+    var form = document.forms[ 'data-form' ],
370
+        items = form['charts-format'];
371
+
372
+    return items[ 0 ].checked ? items[ 0 ].value : items[ 1 ].value;
373
+
374
+}
375
+
376
+/*
377
+ * 禁用非饼图类型的配置项
378
+ */
379
+function disableNotPieConfig() {
380
+
381
+    updateConfigItem( 'disable' );
382
+
383
+}
384
+
385
+/*
386
+ * 启用非饼图类型的配置项
387
+ */
388
+function enableNotPieConfig() {
389
+
390
+    updateConfigItem( 'enable' );
391
+
392
+}
393
+
394
+function updateConfigItem ( value ) {
395
+
396
+    var table = $( "#showTable" )[ 0 ],
397
+        isDisable = value === 'disable' ? true : false;
398
+
399
+    //table中的input处理
400
+    for ( var i = 2 , row; row = table.rows[ i ]; i++ ) {
401
+
402
+        for ( var j = 1, cell; cell = row.cells[ j ]; j++ ) {
403
+
404
+            $( "input", cell ).attr( "disabled", isDisable );
405
+
406
+        }
407
+
408
+    }
409
+
410
+    //其他项处理
411
+    $( "input.not-pie-item" ).attr( "disabled", isDisable );
412
+    $( "#tipInput" ).attr( "disabled", !isDisable )
413
+
414
+}
415
+
416
+/*
417
+ * 获取饼图数据
418
+ * 饼图的数据只取第一行的
419
+ **/
420
+function getSeriesForPieChart () {
421
+
422
+    var series = {
423
+            type: 'pie',
424
+            name: $("#tipInput").val(),
425
+            data: []
426
+        },
427
+        tableData = getTableData();
428
+
429
+
430
+    for ( var j = 1, jlen = tableData[ 0 ].length; j < jlen; j++ ) {
431
+
432
+        var title = tableData[ 0 ][ j ],
433
+            val = tableData[ 1 ][ j ];
434
+
435
+        series.data.push( [ title, val ] );
436
+
437
+    }
438
+
439
+    return {
440
+        series: [ series ]
441
+    };
442
+
443
+}
444
+
445
+function getTableData () {
446
+
447
+    var table = document.getElementById( "showTable" ),
448
+        xCount = table.rows[0].cells.length - 1,
449
+        values = getTableInputValue();
450
+
451
+    for ( var i = 0, value; value = values[ i ]; i++ ) {
452
+
453
+        tableData[ Math.floor( i / xCount ) + 1 ][ i % xCount + 1 ] = values[ i ];
454
+
455
+    }
456
+
457
+    return tableData;
458
+
459
+}
460
+
461
+function getTableInputValue () {
462
+
463
+    var table = document.getElementById( "showTable" ),
464
+        inputs = table.getElementsByTagName( "input" ),
465
+        values = [];
466
+
467
+    for ( var i = 0, input; input = inputs[ i ]; i++ ) {
468
+        values.push( input.value | 0 );
469
+    }
470
+
471
+    return values;
472
+
473
+}
474
+
475
+function getCellValue ( cell ) {
476
+
477
+    var value = utils.trim( ( cell.innerText || cell.textContent || '' ) );
478
+
479
+    return value.replace( new RegExp( UE.dom.domUtils.fillChar, 'g' ), '' ).replace( /^\s+|\s+$/g, '' );
480
+
481
+}
482
+
483
+
484
+//dialog确认事件
485
+dialog.onok = function () {
486
+
487
+    //收集信息
488
+    var form = document.forms[ 'data-form' ],
489
+        info = getUserConfig();
490
+
491
+    //添加图表类型
492
+    info.chartType = currentChartType;
493
+
494
+    //同步表格数据到编辑器
495
+    syncTableData();
496
+
497
+    //执行图表命令
498
+    editor.execCommand( 'charts', info );
499
+
500
+};
501
+
502
+/*
503
+ * 同步图表编辑视图的表格数据到编辑器里的原始表格
504
+ */
505
+function syncTableData () {
506
+
507
+    var tableData = getTableData();
508
+
509
+    for ( var i = 1, row; row = editorTable.rows[ i ]; i++ ) {
510
+
511
+        for ( var j = 1, cell; cell = row.cells[ j ]; j++ ) {
512
+
513
+            cell.innerHTML = tableData[ i ] [ j ];
514
+
515
+        }
516
+
517
+    }
518
+
519
+}

二進制
public/UEditor/dialogs/charts/images/charts0.png


二進制
public/UEditor/dialogs/charts/images/charts1.png


二進制
public/UEditor/dialogs/charts/images/charts2.png


二進制
public/UEditor/dialogs/charts/images/charts3.png


二進制
public/UEditor/dialogs/charts/images/charts4.png


二進制
public/UEditor/dialogs/charts/images/charts5.png


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

@@ -0,0 +1,43 @@
1
+.jd img{
2
+    background:transparent url(images/jxface2.gif?v=1.1) no-repeat scroll left top;
3
+    cursor:pointer;width:35px;height:35px;display:block;
4
+}
5
+.pp img{
6
+    background:transparent url(images/fface.gif?v=1.1) no-repeat scroll left top;
7
+    cursor:pointer;width:25px;height:25px;display:block;
8
+}
9
+.ldw img{
10
+    background:transparent url(images/wface.gif?v=1.1) no-repeat scroll left top;
11
+    cursor:pointer;width:35px;height:35px;display:block;
12
+}
13
+.tsj img{
14
+    background:transparent url(images/tface.gif?v=1.1) no-repeat scroll left top;
15
+    cursor:pointer;width:35px;height:35px;display:block;
16
+}
17
+.cat img{
18
+    background:transparent url(images/cface.gif?v=1.1) no-repeat scroll left top;
19
+    cursor:pointer;width:35px;height:35px;display:block;
20
+}
21
+.bb img{
22
+    background:transparent url(images/bface.gif?v=1.1) no-repeat scroll left top;
23
+    cursor:pointer;width:35px;height:35px;display:block;
24
+}
25
+.youa img{
26
+    background:transparent url(images/yface.gif?v=1.1) no-repeat scroll left top;
27
+    cursor:pointer;width:35px;height:35px;display:block;
28
+}
29
+
30
+.smileytable td {height: 37px;}
31
+#tabPanel{margin-left:5px;overflow: hidden;}
32
+#tabContent {float:left;background:#FFFFFF;}
33
+#tabContent div{display: none;width:480px;overflow:hidden;}
34
+#tabIconReview.show{left:17px;display:block;}
35
+.menuFocus{background:#ACCD3C;}
36
+.menuDefault{background:#FFFFFF;}
37
+#tabIconReview{position:absolute;left:406px;left:398px \9;top:41px;z-index:65533;width:90px;height:76px;}
38
+img.review{width:90px;height:76px;border:2px solid #9cb945;background:#FFFFFF;background-position:center;background-repeat:no-repeat;}
39
+
40
+.wrapper .tabbody{position:relative;float:left;clear:both;padding:10px;width: 95%;}
41
+.tabbody table{width: 100%;}
42
+.tabbody td{border:1px solid #BAC498;}
43
+.tabbody td span{display: block;zoom:1;padding:0 4px;}

文件差異過大導致無法顯示
+ 54 - 0
public/UEditor/dialogs/emotion/emotion.html


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

@@ -0,0 +1,186 @@
1
+window.onload = function () {
2
+    editor.setOpt({
3
+        emotionLocalization:false
4
+    });
5
+
6
+    emotion.SmileyPath = editor.options.emotionLocalization === true ? 'images/' : "http://img.baidu.com/hi/";
7
+    emotion.SmileyBox = createTabList( emotion.tabNum );
8
+    emotion.tabExist = createArr( emotion.tabNum );
9
+
10
+    initImgName();
11
+    initEvtHandler( "tabHeads" );
12
+};
13
+
14
+function initImgName() {
15
+    for ( var pro in emotion.SmilmgName ) {
16
+        var tempName = emotion.SmilmgName[pro],
17
+                tempBox = emotion.SmileyBox[pro],
18
+                tempStr = "";
19
+
20
+        if ( tempBox.length ) return;
21
+        for ( var i = 1; i <= tempName[1]; i++ ) {
22
+            tempStr = tempName[0];
23
+            if ( i < 10 ) tempStr = tempStr + '0';
24
+            tempStr = tempStr + i + '.gif';
25
+            tempBox.push( tempStr );
26
+        }
27
+    }
28
+}
29
+
30
+function initEvtHandler( conId ) {
31
+    var tabHeads = $G( conId );
32
+    for ( var i = 0, j = 0; i < tabHeads.childNodes.length; i++ ) {
33
+        var tabObj = tabHeads.childNodes[i];
34
+        if ( tabObj.nodeType == 1 ) {
35
+            domUtils.on( tabObj, "click", (function ( index ) {
36
+                return function () {
37
+                    switchTab( index );
38
+                };
39
+            })( j ) );
40
+            j++;
41
+        }
42
+    }
43
+    switchTab( 0 );
44
+    $G( "tabIconReview" ).style.display = 'none';
45
+}
46
+
47
+function InsertSmiley( url, evt ) {
48
+    var obj = {
49
+        src:editor.options.emotionLocalization ? editor.options.UEDITOR_HOME_URL + "dialogs/emotion/" + url : url
50
+    };
51
+    obj._src = obj.src;
52
+    editor.execCommand( 'insertimage', obj );
53
+    if ( !evt.ctrlKey ) {
54
+        dialog.popup.hide();
55
+    }
56
+}
57
+
58
+function switchTab( index ) {
59
+
60
+    autoHeight( index );
61
+    if ( emotion.tabExist[index] == 0 ) {
62
+        emotion.tabExist[index] = 1;
63
+        createTab( 'tab' + index );
64
+    }
65
+    //获取呈现元素句柄数组
66
+    var tabHeads = $G( "tabHeads" ).getElementsByTagName( "span" ),
67
+            tabBodys = $G( "tabBodys" ).getElementsByTagName( "div" ),
68
+            i = 0, L = tabHeads.length;
69
+    //隐藏所有呈现元素
70
+    for ( ; i < L; i++ ) {
71
+        tabHeads[i].className = "";
72
+        tabBodys[i].style.display = "none";
73
+    }
74
+    //显示对应呈现元素
75
+    tabHeads[index].className = "focus";
76
+    tabBodys[index].style.display = "block";
77
+}
78
+
79
+function autoHeight( index ) {
80
+    var iframe = dialog.getDom( "iframe" ),
81
+            parent = iframe.parentNode.parentNode;
82
+    switch ( index ) {
83
+        case 0:
84
+            iframe.style.height = "380px";
85
+            parent.style.height = "392px";
86
+            break;
87
+        case 1:
88
+            iframe.style.height = "220px";
89
+            parent.style.height = "232px";
90
+            break;
91
+        case 2:
92
+            iframe.style.height = "260px";
93
+            parent.style.height = "272px";
94
+            break;
95
+        case 3:
96
+            iframe.style.height = "300px";
97
+            parent.style.height = "312px";
98
+            break;
99
+        case 4:
100
+            iframe.style.height = "140px";
101
+            parent.style.height = "152px";
102
+            break;
103
+        case 5:
104
+            iframe.style.height = "260px";
105
+            parent.style.height = "272px";
106
+            break;
107
+        case 6:
108
+            iframe.style.height = "230px";
109
+            parent.style.height = "242px";
110
+            break;
111
+        default:
112
+
113
+    }
114
+}
115
+
116
+
117
+function createTab( tabName ) {
118
+    var faceVersion = "?v=1.1", //版本号
119
+            tab = $G( tabName ), //获取将要生成的Div句柄
120
+            imagePath = emotion.SmileyPath + emotion.imageFolders[tabName], //获取显示表情和预览表情的路径
121
+            positionLine = 11 / 2, //中间数
122
+            iWidth = iHeight = 35, //图片长宽
123
+            iColWidth = 3, //表格剩余空间的显示比例
124
+            tableCss = emotion.imageCss[tabName],
125
+            cssOffset = emotion.imageCssOffset[tabName],
126
+            textHTML = ['<table class="smileytable">'],
127
+            i = 0, imgNum = emotion.SmileyBox[tabName].length, imgColNum = 11, faceImage,
128
+            sUrl, realUrl, posflag, offset, infor;
129
+
130
+    for ( ; i < imgNum; ) {
131
+        textHTML.push( '<tr>' );
132
+        for ( var j = 0; j < imgColNum; j++, i++ ) {
133
+            faceImage = emotion.SmileyBox[tabName][i];
134
+            if ( faceImage ) {
135
+                sUrl = imagePath + faceImage + faceVersion;
136
+                realUrl = imagePath + faceImage;
137
+                posflag = j < positionLine ? 0 : 1;
138
+                offset = cssOffset * i * (-1) - 1;
139
+                infor = emotion.SmileyInfor[tabName][i];
140
+
141
+                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)">' );
142
+                textHTML.push( '<span>' );
143
+                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>' );
144
+                textHTML.push( '</span>' );
145
+            } else {
146
+                textHTML.push( '<td width="' + iColWidth + '%"   bgcolor="#FFFFFF">' );
147
+            }
148
+            textHTML.push( '</td>' );
149
+        }
150
+        textHTML.push( '</tr>' );
151
+    }
152
+    textHTML.push( '</table>' );
153
+    textHTML = textHTML.join( "" );
154
+    tab.innerHTML = textHTML;
155
+}
156
+
157
+function over( td, srcPath, posFlag ) {
158
+    td.style.backgroundColor = "#ACCD3C";
159
+    $G( 'faceReview' ).style.backgroundImage = "url(" + srcPath + ")";
160
+    if ( posFlag == 1 ) $G( "tabIconReview" ).className = "show";
161
+    $G( "tabIconReview" ).style.display = 'block';
162
+}
163
+
164
+function out( td ) {
165
+    td.style.backgroundColor = "transparent";
166
+    var tabIconRevew = $G( "tabIconReview" );
167
+    tabIconRevew.className = "";
168
+    tabIconRevew.style.display = 'none';
169
+}
170
+
171
+function createTabList( tabNum ) {
172
+    var obj = {};
173
+    for ( var i = 0; i < tabNum; i++ ) {
174
+        obj["tab" + i] = [];
175
+    }
176
+    return obj;
177
+}
178
+
179
+function createArr( tabNum ) {
180
+    var arr = [];
181
+    for ( var i = 0; i < tabNum; i++ ) {
182
+        arr[i] = 0;
183
+    }
184
+    return arr;
185
+}
186
+

二進制
public/UEditor/dialogs/emotion/images/0.gif


二進制
public/UEditor/dialogs/emotion/images/bface.gif


二進制
public/UEditor/dialogs/emotion/images/cface.gif


二進制
public/UEditor/dialogs/emotion/images/fface.gif


二進制
public/UEditor/dialogs/emotion/images/jxface2.gif


二進制
public/UEditor/dialogs/emotion/images/neweditor-tab-bg.png


二進制
public/UEditor/dialogs/emotion/images/tface.gif


二進制
public/UEditor/dialogs/emotion/images/wface.gif


二進制
public/UEditor/dialogs/emotion/images/yface.gif


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

@@ -0,0 +1,89 @@
1
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+        "http://www.w3.org/TR/html4/loose.dtd">
3
+<html>
4
+<head>
5
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
6
+    <title></title>
7
+    <script type="text/javascript" src="../internal.js"></script>
8
+    <style type="text/css">
9
+        .content{width:530px; height: 350px;margin: 10px auto;}
10
+        .content table{width: 100%}
11
+        .content table td{vertical-align: middle;}
12
+        #address{width:220px;height:21px;background: #FFF;border:1px solid #d7d7d7; line-height: 21px;}
13
+    </style>
14
+    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
15
+</head>
16
+<body>
17
+<div class="content">
18
+    <table>
19
+        <tr>
20
+            <td><label for="address"><var id="lang_input_address"></var></label></td>
21
+            <td><input id="address" type="text" /></td>
22
+            <td><a id="doSearch" href="javascript:void(0)" class="button"><var id="lang_input_search"></var></a></td>
23
+        </tr>
24
+    </table>
25
+    <div id="container" style="width: 100%; height: 340px;margin: 5px auto; border: 1px solid gray;"></div>
26
+</div>
27
+<script type="text/javascript">
28
+    domUtils.on(window,"load",function(){
29
+        var map = new google.maps.Map(document.getElementById('container'), {
30
+                zoom: 3,
31
+                streetViewControl: false,
32
+                scaleControl: true,
33
+                mapTypeId: google.maps.MapTypeId.ROADMAP
34
+            });
35
+            var imgcss;
36
+            var marker = new google.maps.Marker({
37
+                map: map,
38
+                draggable: true
39
+            });
40
+            function doSearch(){
41
+                var address = document.getElementById('address').value;
42
+                var geocoder = new google.maps.Geocoder();
43
+                geocoder.geocode( { 'address': address}, function (results, status) {
44
+                    if (status == google.maps.GeocoderStatus.OK) {
45
+                        var bounds = results[0].geometry.viewport;
46
+                        map.fitBounds(bounds);
47
+                        marker.setPosition(results[0].geometry.location);
48
+                        marker.setTitle(address);
49
+                    } else alert(lang.searchError);
50
+                });
51
+            }
52
+            $G('address').onkeydown = function (evt){
53
+                evt = evt || event;
54
+                if (evt.keyCode == 13) {
55
+                    doSearch();
56
+                }
57
+            };
58
+            $G("doSearch").onclick = doSearch;
59
+            dialog.onok = function (){
60
+                var center = map.getCenter();
61
+                var point = marker.getPosition();
62
+                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";
63
+                editor.execCommand('inserthtml', '<img width="520" height="340" src="' + url + '"' + (imgcss ? ' style="' + imgcss + '"' :'') + '/>');
64
+            };
65
+
66
+            function getPars(str,par){
67
+                var reg = new RegExp(par+"=((\\d+|[.,])*)","g");
68
+                return reg.exec(str)[1];
69
+            }
70
+            var img = editor.selection.getRange().getClosedNode();
71
+            if(img && img.src.indexOf("http://maps.googleapis.com/maps/api/staticmap")!=-1){
72
+                var url = img.getAttribute("src");
73
+                var centers = getPars(url,"center").split(",");
74
+                point = new google.maps.LatLng(Number(centers[0]),Number(centers[1]));
75
+                map.setCenter(point);
76
+                map.setZoom(Number(getPars(url,"zoom")));
77
+                centers = getPars(url,"markers").split(",");
78
+                marker.setPosition(new google.maps.LatLng(Number(centers[0]),Number(centers[1])));
79
+                imgcss = img.style.cssText;
80
+            }else{
81
+                setTimeout(function(){
82
+                    doSearch();
83
+                },30)
84
+            }
85
+    });
86
+
87
+</script>
88
+</body>
89
+</html>

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

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

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

@@ -0,0 +1,82 @@
1
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
2
+        "http://www.w3.org/TR/html4/loose.dtd">
3
+<html>
4
+<head>
5
+    <title>帮助</title>
6
+    <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
7
+    <script type="text/javascript" src="../internal.js"></script>
8
+    <link rel="stylesheet" type="text/css" href="help.css">
9
+</head>
10
+<body>
11
+<div class="wrapper" id="helptab">
12
+    <div id="tabHeads" class="tabhead">
13
+        <span class="focus" tabsrc="about"><var id="lang_input_about"></var></span>
14
+        <span tabsrc="shortcuts"><var id="lang_input_shortcuts"></var></span>
15
+    </div>
16
+    <div id="tabBodys" class="tabbody">
17
+        <div id="about" class="panel">
18
+            <h1>UEditor</h1>
19
+            <p id="version"></p>
20
+            <p><var id="lang_input_introduction"></var></p>
21
+        </div>
22
+        <div id="shortcuts" class="panel">
23
+            <table>
24
+                <thead>
25
+                <tr>
26
+                    <td><var id="lang_Txt_shortcuts"></var></td>
27
+                    <td><var id="lang_Txt_func"></var></td>
28
+                </tr>
29
+                </thead>
30
+                <tbody>
31
+                <tr>
32
+                    <td>ctrl+b</td>
33
+                    <td><var id="lang_Txt_bold"></var></td>
34
+                </tr>
35
+                <tr>
36
+                    <td>ctrl+c</td>
37
+                    <td><var id="lang_Txt_copy"></var></td>
38
+                </tr>
39
+                <tr>
40
+                    <td>ctrl+x</td>
41
+                    <td><var id="lang_Txt_cut"></var></td>
42
+                </tr>
43
+                <tr>
44
+                    <td>ctrl+v</td>
45
+                    <td><var id="lang_Txt_Paste"></var></td>
46
+                </tr>
47
+                <tr>
48
+                    <td>ctrl+y</td>
49
+                    <td><var id="lang_Txt_undo"></var></td>
50
+                </tr>
51
+                <tr>
52
+                    <td>ctrl+z</td>
53
+                    <td><var id="lang_Txt_redo"></var></td>
54
+                </tr>
55
+                <tr>
56
+                    <td>ctrl+i</td>
57
+                    <td><var id="lang_Txt_italic"></var></td>
58
+                </tr>
59
+                <tr>
60
+                    <td>ctrl+u</td>
61
+                    <td><var id="lang_Txt_underline"></var></td>
62
+                </tr>
63
+                <tr>
64
+                    <td>ctrl+a</td>
65
+                    <td><var id="lang_Txt_selectAll"></var></td>
66
+                </tr>
67
+                <tr>
68
+                    <td>shift+enter</td>
69
+                    <td><var id="lang_Txt_visualEnter"></var></td>
70
+                </tr>
71
+                <tr>
72
+                    <td>alt+z</td>
73
+                    <td><var id="lang_Txt_fullscreen"></var></td>
74
+                </tr>
75
+                </tbody>
76
+            </table>
77
+        </div>
78
+    </div>
79
+</div>
80
+<script type="text/javascript" src="help.js"></script>
81
+</body>
82
+</html>

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

@@ -0,0 +1,56 @@
1
+/**
2
+ * Created with JetBrains PhpStorm.
3
+ * User: xuheng
4
+ * Date: 12-9-26
5
+ * Time: 下午1:06
6
+ * To change this template use File | Settings | File Templates.
7
+ */
8
+/**
9
+ * tab点击处理事件
10
+ * @param tabHeads
11
+ * @param tabBodys
12
+ * @param obj
13
+ */
14
+function clickHandler( tabHeads,tabBodys,obj ) {
15
+    //head样式更改
16
+    for ( var k = 0, len = tabHeads.length; k < len; k++ ) {
17
+        tabHeads[k].className = "";
18
+    }
19
+    obj.className = "focus";
20
+    //body显隐
21
+    var tabSrc = obj.getAttribute( "tabSrc" );
22
+    for ( var j = 0, length = tabBodys.length; j < length; j++ ) {
23
+        var body = tabBodys[j],
24
+            id = body.getAttribute( "id" );
25
+        body.onclick = function(){
26
+            this.style.zoom = 1;
27
+        };
28
+        if ( id != tabSrc ) {
29
+            body.style.zIndex = 1;
30
+        } else {
31
+            body.style.zIndex = 200;
32
+        }
33
+    }
34
+
35
+}
36
+
37
+/**
38
+ * TAB切换
39
+ * @param tabParentId  tab的父节点ID或者对象本身
40
+ */
41
+function switchTab( tabParentId ) {
42
+    var tabElements = $G( tabParentId ).children,
43
+        tabHeads = tabElements[0].children,
44
+        tabBodys = tabElements[1].children;
45
+
46
+    for ( var i = 0, length = tabHeads.length; i < length; i++ ) {
47
+        var head = tabHeads[i];
48
+        if ( head.className === "focus" )clickHandler(tabHeads,tabBodys, head );
49
+        head.onclick = function () {
50
+            clickHandler(tabHeads,tabBodys,this);
51
+        }
52
+    }
53
+}
54
+switchTab("helptab");
55
+
56
+document.getElementById('version').innerHTML = parent.UE.version;

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

@@ -0,0 +1,894 @@
1
+@charset "utf-8";
2
+/* dialog样式 */
3
+.wrapper {
4
+    zoom: 1;
5
+    width: 630px;
6
+    *width: 626px;
7
+    height: 380px;
8
+    margin: 0 auto;
9
+    padding: 10px;
10
+    position: relative;
11
+    font-family: sans-serif;
12
+}
13
+
14
+/*tab样式框大小*/
15
+.tabhead {
16
+    float:left;
17
+}
18
+.tabbody {
19
+    width: 100%;
20
+    height: 346px;
21
+    position: relative;
22
+    clear: both;
23
+}
24
+
25
+.tabbody .panel {
26
+    position: absolute;
27
+    width: 0;
28
+    height: 0;
29
+    background: #fff;
30
+    overflow: hidden;
31
+    display: none;
32
+}
33
+
34
+.tabbody .panel.focus {
35
+    width: 100%;
36
+    height: 346px;
37
+    display: block;
38
+}
39
+
40
+/* 图片对齐方式 */
41
+.alignBar{
42
+    float:right;
43
+    margin-top: 5px;
44
+    position: relative;
45
+}
46
+
47
+.alignBar .algnLabel{
48
+    float:left;
49
+    height: 20px;
50
+    line-height: 20px;
51
+}
52
+
53
+.alignBar #alignIcon{
54
+    zoom:1;
55
+    _display: inline;
56
+    display: inline-block;
57
+    position: relative;
58
+}
59
+.alignBar #alignIcon span{
60
+    float: left;
61
+    cursor: pointer;
62
+    display: block;
63
+    width: 19px;
64
+    height: 17px;
65
+    margin-right: 3px;
66
+    margin-left: 3px;
67
+    background-image: url(./images/alignicon.jpg);
68
+}
69
+.alignBar #alignIcon .none-align{
70
+    background-position: 0 -18px;
71
+}
72
+.alignBar #alignIcon .left-align{
73
+    background-position: -20px -18px;
74
+}
75
+.alignBar #alignIcon .right-align{
76
+    background-position: -40px -18px;
77
+}
78
+.alignBar #alignIcon .center-align{
79
+    background-position: -60px -18px;
80
+}
81
+.alignBar #alignIcon .none-align.focus{
82
+    background-position: 0 0;
83
+}
84
+.alignBar #alignIcon .left-align.focus{
85
+    background-position: -20px 0;
86
+}
87
+.alignBar #alignIcon .right-align.focus{
88
+    background-position: -40px 0;
89
+}
90
+.alignBar #alignIcon .center-align.focus{
91
+    background-position: -60px 0;
92
+}
93
+
94
+
95
+
96
+
97
+/* 远程图片样式 */
98
+#remote {
99
+    z-index: 200;
100
+}
101
+
102
+#remote .top{
103
+    width: 100%;
104
+    margin-top: 25px;
105
+}
106
+#remote .left{
107
+    display: block;
108
+    float: left;
109
+    width: 300px;
110
+    height:10px;
111
+}
112
+#remote .right{
113
+    display: block;
114
+    float: right;
115
+    width: 300px;
116
+    height:10px;
117
+}
118
+#remote .row{
119
+    margin-left: 20px;
120
+    clear: both;
121
+    height: 40px;
122
+}
123
+
124
+#remote .row label{
125
+    text-align: center;
126
+    width: 50px;
127
+    zoom:1;
128
+    _display: inline;
129
+    display:inline-block;
130
+    vertical-align: middle;
131
+}
132
+#remote .row label.algnLabel{
133
+    float: left;
134
+
135
+}
136
+
137
+#remote input.text{
138
+    width: 150px;
139
+    padding: 3px 6px;
140
+    font-size: 14px;
141
+    line-height: 1.42857143;
142
+    color: #555;
143
+    background-color: #fff;
144
+    background-image: none;
145
+    border: 1px solid #ccc;
146
+    border-radius: 4px;
147
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
148
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
149
+    -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
150
+    transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
151
+}
152
+#remote input.text:focus {
153
+    border-color: #66afe9;
154
+    outline: 0;
155
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
156
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
157
+}
158
+#remote #url{
159
+    width: 500px;
160
+    margin-bottom: 2px;
161
+}
162
+#remote #width,
163
+#remote #height{
164
+    width: 20px;
165
+    margin-left: 2px;
166
+    margin-right: 2px;
167
+}
168
+#remote #border,
169
+#remote #vhSpace,
170
+#remote #title{
171
+    width: 180px;
172
+    margin-right: 5px;
173
+}
174
+#remote #lock{
175
+}
176
+#remote #lockicon{
177
+    zoom: 1;
178
+    _display:inline;
179
+    display: inline-block;
180
+    width: 20px;
181
+    height: 20px;
182
+    background: url("../../themes/default/images/lock.gif") -13px -13px no-repeat;
183
+    vertical-align: middle;
184
+}
185
+#remote #preview{
186
+    clear: both;
187
+    width: 260px;
188
+    height: 240px;
189
+    z-index: 9999;
190
+    margin-top: 10px;
191
+    background-color: #eee;
192
+    overflow: hidden;
193
+}
194
+
195
+/* 上传图片 */
196
+.tabbody #upload.panel {
197
+    width: 0;
198
+    height: 0;
199
+    overflow: hidden;
200
+    position: absolute !important;
201
+    clip: rect(1px, 1px, 1px, 1px);
202
+    background: #fff;
203
+    display: block;
204
+}
205
+
206
+.tabbody #upload.panel.focus {
207
+    width: 100%;
208
+    height: 346px;
209
+    display: block;
210
+    clip: auto;
211
+}
212
+
213
+#upload .queueList {
214
+    margin: 0;
215
+    width: 100%;
216
+    height: 100%;
217
+    position: absolute;
218
+    overflow: hidden;
219
+}
220
+
221
+#upload p {
222
+    margin: 0;
223
+}
224
+
225
+.element-invisible {
226
+    width: 0 !important;
227
+    height: 0 !important;
228
+    border: 0;
229
+    padding: 0;
230
+    margin: 0;
231
+    overflow: hidden;
232
+    position: absolute !important;
233
+    clip: rect(1px, 1px, 1px, 1px);
234
+}
235
+
236
+#upload .placeholder {
237
+    margin: 10px;
238
+    border: 2px dashed #e6e6e6;
239
+    *border: 0px dashed #e6e6e6;
240
+    height: 172px;
241
+    padding-top: 150px;
242
+    text-align: center;
243
+    background: url(./images/image.png) center 70px no-repeat;
244
+    color: #cccccc;
245
+    font-size: 18px;
246
+    position: relative;
247
+    top:0;
248
+    *top: 10px;
249
+}
250
+
251
+#upload .placeholder .webuploader-pick {
252
+    font-size: 18px;
253
+    background: #00b7ee;
254
+    border-radius: 3px;
255
+    line-height: 44px;
256
+    padding: 0 30px;
257
+    *width: 120px;
258
+    color: #fff;
259
+    display: inline-block;
260
+    margin: 0 auto 20px auto;
261
+    cursor: pointer;
262
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
263
+}
264
+
265
+#upload .placeholder .webuploader-pick-hover {
266
+    background: #00a2d4;
267
+}
268
+
269
+
270
+#filePickerContainer {
271
+    text-align: center;
272
+}
273
+
274
+#upload .placeholder .flashTip {
275
+    color: #666666;
276
+    font-size: 12px;
277
+    position: absolute;
278
+    width: 100%;
279
+    text-align: center;
280
+    bottom: 20px;
281
+}
282
+
283
+#upload .placeholder .flashTip a {
284
+    color: #0785d1;
285
+    text-decoration: none;
286
+}
287
+
288
+#upload .placeholder .flashTip a:hover {
289
+    text-decoration: underline;
290
+}
291
+
292
+#upload .placeholder.webuploader-dnd-over {
293
+    border-color: #999999;
294
+}
295
+
296
+#upload .filelist {
297
+    list-style: none;
298
+    margin: 0;
299
+    padding: 0;
300
+    overflow-x: hidden;
301
+    overflow-y: auto;
302
+    position: relative;
303
+    height: 300px;
304
+}
305
+
306
+#upload .filelist:after {
307
+    content: '';
308
+    display: block;
309
+    width: 0;
310
+    height: 0;
311
+    overflow: hidden;
312
+    clear: both;
313
+    position: relative;
314
+}
315
+
316
+#upload .filelist li {
317
+    width: 113px;
318
+    height: 113px;
319
+    background: url(./images/bg.png);
320
+    text-align: center;
321
+    margin: 9px 0 0 9px;
322
+    *margin: 6px 0 0 6px;
323
+    position: relative;
324
+    display: block;
325
+    float: left;
326
+    overflow: hidden;
327
+    font-size: 12px;
328
+}
329
+
330
+#upload .filelist li p.log {
331
+    position: relative;
332
+    top: -45px;
333
+}
334
+
335
+#upload .filelist li p.title {
336
+    position: absolute;
337
+    top: 0;
338
+    left: 0;
339
+    width: 100%;
340
+    overflow: hidden;
341
+    white-space: nowrap;
342
+    text-overflow: ellipsis;
343
+    top: 5px;
344
+    text-indent: 5px;
345
+    text-align: left;
346
+}
347
+
348
+#upload .filelist li p.progress {
349
+    position: absolute;
350
+    width: 100%;
351
+    bottom: 0;
352
+    left: 0;
353
+    height: 8px;
354
+    overflow: hidden;
355
+    z-index: 50;
356
+    margin: 0;
357
+    border-radius: 0;
358
+    background: none;
359
+    -webkit-box-shadow: 0 0 0;
360
+}
361
+
362
+#upload .filelist li p.progress span {
363
+    display: none;
364
+    overflow: hidden;
365
+    width: 0;
366
+    height: 100%;
367
+    background: #1483d8 url(./images/progress.png) repeat-x;
368
+
369
+    -webit-transition: width 200ms linear;
370
+    -moz-transition: width 200ms linear;
371
+    -o-transition: width 200ms linear;
372
+    -ms-transition: width 200ms linear;
373
+    transition: width 200ms linear;
374
+
375
+    -webkit-animation: progressmove 2s linear infinite;
376
+    -moz-animation: progressmove 2s linear infinite;
377
+    -o-animation: progressmove 2s linear infinite;
378
+    -ms-animation: progressmove 2s linear infinite;
379
+    animation: progressmove 2s linear infinite;
380
+
381
+    -webkit-transform: translateZ(0);
382
+}
383
+
384
+@-webkit-keyframes progressmove {
385
+    0% {
386
+        background-position: 0 0;
387
+    }
388
+    100% {
389
+        background-position: 17px 0;
390
+    }
391
+}
392
+
393
+@-moz-keyframes progressmove {
394
+    0% {
395
+        background-position: 0 0;
396
+    }
397
+    100% {
398
+        background-position: 17px 0;
399
+    }
400
+}
401
+
402
+@keyframes progressmove {
403
+    0% {
404
+        background-position: 0 0;
405
+    }
406
+    100% {
407
+        background-position: 17px 0;
408
+    }
409
+}
410
+
411
+#upload .filelist li p.imgWrap {
412
+    position: relative;
413
+    z-index: 2;
414
+    line-height: 113px;
415
+    vertical-align: middle;
416
+    overflow: hidden;
417
+    width: 113px;
418
+    height: 113px;
419
+
420
+    -webkit-transform-origin: 50% 50%;
421
+    -moz-transform-origin: 50% 50%;
422
+    -o-transform-origin: 50% 50%;
423
+    -ms-transform-origin: 50% 50%;
424
+    transform-origin: 50% 50%;
425
+
426
+    -webit-transition: 200ms ease-out;
427
+    -moz-transition: 200ms ease-out;
428
+    -o-transition: 200ms ease-out;
429
+    -ms-transition: 200ms ease-out;
430
+    transition: 200ms ease-out;
431
+}
432
+
433
+#upload .filelist li img {
434
+    width: 100%;
435
+}
436
+
437
+#upload .filelist li p.error {
438
+    background: #f43838;
439
+    color: #fff;
440
+    position: absolute;
441
+    bottom: 0;
442
+    left: 0;
443
+    height: 28px;
444
+    line-height: 28px;
445
+    width: 100%;
446
+    z-index: 100;
447
+    display:none;
448
+}
449
+
450
+#upload .filelist li .success {
451
+    display: block;
452
+    position: absolute;
453
+    left: 0;
454
+    bottom: 0;
455
+    height: 40px;
456
+    width: 100%;
457
+    z-index: 200;
458
+    background: url(./images/success.png) no-repeat right bottom;
459
+    background: url(./images/success.gif) no-repeat right bottom \9;
460
+}
461
+
462
+#upload .filelist li.filePickerBlock {
463
+    width: 113px;
464
+    height: 113px;
465
+    background: url(./images/image.png) no-repeat center 12px;
466
+    border: 1px solid #eeeeee;
467
+    border-radius: 0;
468
+}
469
+#upload .filelist li.filePickerBlock div.webuploader-pick  {
470
+    width: 100%;
471
+    height: 100%;
472
+    margin: 0;
473
+    padding: 0;
474
+    opacity: 0;
475
+    background: none;
476
+    font-size: 0;
477
+}
478
+
479
+#upload .filelist div.file-panel {
480
+    position: absolute;
481
+    height: 0;
482
+    filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0;
483
+    background: rgba(0, 0, 0, 0.5);
484
+    width: 100%;
485
+    top: 0;
486
+    left: 0;
487
+    overflow: hidden;
488
+    z-index: 300;
489
+}
490
+
491
+#upload .filelist div.file-panel span {
492
+    width: 24px;
493
+    height: 24px;
494
+    display: inline;
495
+    float: right;
496
+    text-indent: -9999px;
497
+    overflow: hidden;
498
+    background: url(./images/icons.png) no-repeat;
499
+    background: url(./images/icons.gif) no-repeat \9;
500
+    margin: 5px 1px 1px;
501
+    cursor: pointer;
502
+    -webkit-tap-highlight-color: rgba(0,0,0,0);
503
+    -webkit-user-select: none;
504
+    -moz-user-select: none;
505
+    -ms-user-select: none;
506
+    user-select: none;
507
+}
508
+
509
+#upload .filelist div.file-panel span.rotateLeft {
510
+    display:none;
511
+    background-position: 0 -24px;
512
+}
513
+
514
+#upload .filelist div.file-panel span.rotateLeft:hover {
515
+    background-position: 0 0;
516
+}
517
+
518
+#upload .filelist div.file-panel span.rotateRight {
519
+    display:none;
520
+    background-position: -24px -24px;
521
+}
522
+
523
+#upload .filelist div.file-panel span.rotateRight:hover {
524
+    background-position: -24px 0;
525
+}
526
+
527
+#upload .filelist div.file-panel span.cancel {
528
+    background-position: -48px -24px;
529
+}
530
+
531
+#upload .filelist div.file-panel span.cancel:hover {
532
+    background-position: -48px 0;
533
+}
534
+
535
+#upload .statusBar {
536
+    height: 45px;
537
+    border-bottom: 1px solid #dadada;
538
+    margin: 0 10px;
539
+    padding: 0;
540
+    line-height: 45px;
541
+    vertical-align: middle;
542
+    position: relative;
543
+}
544
+
545
+#upload .statusBar .progress {
546
+    border: 1px solid #1483d8;
547
+    width: 198px;
548
+    background: #fff;
549
+    height: 18px;
550
+    position: absolute;
551
+    top: 12px;
552
+    display: none;
553
+    text-align: center;
554
+    line-height: 18px;
555
+    color: #6dbfff;
556
+    margin: 0 10px 0 0;
557
+}
558
+#upload .statusBar .progress span.percentage {
559
+    width: 0;
560
+    height: 100%;
561
+    left: 0;
562
+    top: 0;
563
+    background: #1483d8;
564
+    position: absolute;
565
+}
566
+#upload .statusBar .progress span.text {
567
+    position: relative;
568
+    z-index: 10;
569
+}
570
+
571
+#upload .statusBar .info {
572
+    display: inline-block;
573
+    font-size: 14px;
574
+    color: #666666;
575
+}
576
+
577
+#upload .statusBar .btns {
578
+    position: absolute;
579
+    top: 7px;
580
+    right: 0;
581
+    line-height: 30px;
582
+}
583
+
584
+#filePickerBtn {
585
+    display: inline-block;
586
+    float: left;
587
+}
588
+#upload .statusBar .btns .webuploader-pick,
589
+#upload .statusBar .btns .uploadBtn,
590
+#upload .statusBar .btns .uploadBtn.state-uploading,
591
+#upload .statusBar .btns .uploadBtn.state-paused {
592
+    background: #ffffff;
593
+    border: 1px solid #cfcfcf;
594
+    color: #565656;
595
+    padding: 0 18px;
596
+    display: inline-block;
597
+    border-radius: 3px;
598
+    margin-left: 10px;
599
+    cursor: pointer;
600
+    font-size: 14px;
601
+    float: left;
602
+    -webkit-user-select: none;
603
+    -moz-user-select: none;
604
+    -ms-user-select: none;
605
+    user-select: none;
606
+}
607
+#upload .statusBar .btns .webuploader-pick-hover,
608
+#upload .statusBar .btns .uploadBtn:hover,
609
+#upload .statusBar .btns .uploadBtn.state-uploading:hover,
610
+#upload .statusBar .btns .uploadBtn.state-paused:hover {
611
+    background: #f0f0f0;
612
+}
613
+
614
+#upload .statusBar .btns .uploadBtn,
615
+#upload .statusBar .btns .uploadBtn.state-paused{
616
+    background: #00b7ee;
617
+    color: #fff;
618
+    border-color: transparent;
619
+}
620
+#upload .statusBar .btns .uploadBtn:hover,
621
+#upload .statusBar .btns .uploadBtn.state-paused:hover{
622
+    background: #00a2d4;
623
+}
624
+
625
+#upload .statusBar .btns .uploadBtn.disabled {
626
+    pointer-events: none;
627
+    filter:alpha(opacity=60);
628
+    -moz-opacity:0.6;
629
+    -khtml-opacity: 0.6;
630
+    opacity: 0.6;
631
+}
632
+
633
+
634
+
635
+/* 图片管理样式 */
636
+#online {
637
+    width: 100%;
638
+    height: 336px;
639
+    padding: 10px 0 0 0;
640
+}
641
+#online #imageList{
642
+    width: 100%;
643
+    height: 100%;
644
+    overflow-x: hidden;
645
+    overflow-y: auto;
646
+    position: relative;
647
+}
648
+#online ul {
649
+    display: block;
650
+    list-style: none;
651
+    margin: 0;
652
+    padding: 0;
653
+}
654
+#online li {
655
+    float: left;
656
+    display: block;
657
+    list-style: none;
658
+    padding: 0;
659
+    width: 113px;
660
+    height: 113px;
661
+    margin: 0 0 9px 9px;
662
+    *margin: 0 0 6px 6px;
663
+    background-color: #eee;
664
+    overflow: hidden;
665
+    cursor: pointer;
666
+    position: relative;
667
+}
668
+#online li.clearFloat {
669
+    float: none;
670
+    clear: both;
671
+    display: block;
672
+    width:0;
673
+    height:0;
674
+    margin: 0;
675
+    padding: 0;
676
+}
677
+#online li img {
678
+    cursor: pointer;
679
+}
680
+#online li .icon {
681
+    cursor: pointer;
682
+    width: 113px;
683
+    height: 113px;
684
+    position: absolute;
685
+    top: 0;
686
+    left: 0;
687
+    z-index: 2;
688
+    border: 0;
689
+    background-repeat: no-repeat;
690
+}
691
+#online li .icon:hover {
692
+    width: 107px;
693
+    height: 107px;
694
+    border: 3px solid #1094fa;
695
+}
696
+#online li.selected .icon {
697
+    background-image: url(images/success.png);
698
+    background-image: url(images/success.gif)\9;
699
+    background-position: 75px 75px;
700
+}
701
+#online li.selected .icon:hover {
702
+    width: 107px;
703
+    height: 107px;
704
+    border: 3px solid #1094fa;
705
+    background-position: 72px 72px;
706
+}
707
+
708
+
709
+/* 图片搜索样式 */
710
+#search .searchBar {
711
+    width: 100%;
712
+    height: 30px;
713
+    margin: 10px 0 5px 0;
714
+    padding: 0;
715
+}
716
+
717
+#search input.text{
718
+    width: 150px;
719
+    padding: 3px 6px;
720
+    font-size: 14px;
721
+    line-height: 1.42857143;
722
+    color: #555;
723
+    background-color: #fff;
724
+    background-image: none;
725
+    border: 1px solid #ccc;
726
+    border-radius: 4px;
727
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
728
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
729
+    -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
730
+    transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
731
+}
732
+#search input.text:focus {
733
+    border-color: #66afe9;
734
+    outline: 0;
735
+    -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
736
+    box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6);
737
+}
738
+#search input.searchTxt {
739
+    margin-left:5px;
740
+    padding-left: 5px;
741
+    background: #FFF;
742
+    width: 300px;
743
+    *width: 260px;
744
+    height: 21px;
745
+    line-height: 21px;
746
+    float: left;
747
+    dislay: block;
748
+}
749
+
750
+#search .searchType {
751
+    width: 65px;
752
+    height: 28px;
753
+    padding:0;
754
+    line-height: 28px;
755
+    border: 1px solid #d7d7d7;
756
+    border-radius: 0;
757
+    vertical-align: top;
758
+    margin-left: 5px;
759
+    float: left;
760
+    dislay: block;
761
+}
762
+
763
+#search #searchBtn,
764
+#search #searchReset {
765
+    display: inline-block;
766
+    margin-bottom: 0;
767
+    margin-right: 5px;
768
+    padding: 4px 10px;
769
+    font-weight: 400;
770
+    text-align: center;
771
+    vertical-align: middle;
772
+    cursor: pointer;
773
+    background-image: none;
774
+    border: 1px solid transparent;
775
+    white-space: nowrap;
776
+    font-size: 14px;
777
+    border-radius: 4px;
778
+    -webkit-user-select: none;
779
+    -moz-user-select: none;
780
+    -ms-user-select: none;
781
+    user-select: none;
782
+    vertical-align: top;
783
+    float: right;
784
+}
785
+
786
+#search #searchBtn {
787
+    color: white;
788
+    border-color: #285e8e;
789
+    background-color: #3b97d7;
790
+}
791
+#search #searchReset {
792
+    color: #333;
793
+    border-color: #ccc;
794
+    background-color: #fff;
795
+}
796
+#search #searchBtn:hover {
797
+    background-color: #3276b1;
798
+}
799
+#search #searchReset:hover {
800
+    background-color: #eee;
801
+}
802
+
803
+#search .msg {
804
+    margin-left: 5px;
805
+}
806
+
807
+#search .searchList{
808
+    width: 100%;
809
+    height: 300px;
810
+    overflow: hidden;
811
+    clear: both;
812
+}
813
+#search .searchList ul{
814
+    margin:0;
815
+    padding:0;
816
+    list-style:none;
817
+    clear: both;
818
+    width: 100%;
819
+    height: 100%;
820
+    overflow-x: hidden;
821
+    overflow-y: auto;
822
+    zoom: 1;
823
+    position: relative;
824
+}
825
+
826
+#search .searchList li {
827
+    list-style:none;
828
+    float: left;
829
+    display: block;
830
+    width: 115px;
831
+    margin: 5px 10px 5px 20px;
832
+    *margin: 5px 10px 5px 15px;
833
+    padding:0;
834
+    font-size: 12px;
835
+    box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
836
+    -moz-box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
837
+    -webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .3);
838
+    position: relative;
839
+    vertical-align: top;
840
+    text-align: center;
841
+    overflow: hidden;
842
+    cursor: pointer;
843
+    filter: alpha(Opacity=100);
844
+    -moz-opacity: 1;
845
+    opacity: 1;
846
+    border: 2px solid #eee;
847
+}
848
+
849
+#search .searchList li.selected {
850
+    filter: alpha(Opacity=40);
851
+    -moz-opacity: 0.4;
852
+    opacity: 0.4;
853
+    border: 2px solid #00a0e9;
854
+}
855
+
856
+#search .searchList li p {
857
+    background-color: #eee;
858
+    margin: 0;
859
+    padding: 0;
860
+    position: relative;
861
+    width:100%;
862
+    height:115px;
863
+    overflow: hidden;
864
+}
865
+
866
+#search .searchList li p img {
867
+    cursor: pointer;
868
+    border: 0;
869
+}
870
+
871
+#search .searchList li a {
872
+    color: #999;
873
+    border-top: 1px solid #F2F2F2;
874
+    background: #FAFAFA;
875
+    text-align: center;
876
+    display: block;
877
+    padding: 0 5px;
878
+    width: 105px;
879
+    height:32px;
880
+    line-height:32px;
881
+    white-space:nowrap;
882
+    text-overflow:ellipsis;
883
+    text-decoration: none;
884
+    overflow: hidden;
885
+    word-break: break-all;
886
+}
887
+
888
+#search .searchList a:hover {
889
+    text-decoration: underline;
890
+    color: #333;
891
+}
892
+#search .searchList .clearFloat{
893
+    clear: both;
894
+}

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

@@ -0,0 +1,120 @@
1
+<!doctype html>
2
+<html>
3
+<head>
4
+    <meta charset="UTF-8">
5
+    <title>ueditor图片对话框</title>
6
+    <script type="text/javascript" src="../internal.js"></script>
7
+
8
+    <!-- jquery -->
9
+    <script type="text/javascript" src="../../third-party/jquery-1.10.2.min.js"></script>
10
+
11
+    <!-- webuploader -->
12
+    <script src="../../third-party/webuploader/webuploader.min.js"></script>
13
+    <link rel="stylesheet" type="text/css" href="../../third-party/webuploader/webuploader.css">
14
+
15
+    <!-- image dialog -->
16
+    <link rel="stylesheet" href="image.css" type="text/css" />
17
+</head>
18
+<body>
19
+
20
+    <div class="wrapper">
21
+        <div id="tabhead" class="tabhead">
22
+            <span class="tab" data-content-id="remote"><var id="lang_tab_remote"></var></span>
23
+            <span class="tab focus" data-content-id="upload"><var id="lang_tab_upload"></var></span>
24
+            <span class="tab" data-content-id="online"><var id="lang_tab_online"></var></span>
25
+            <span class="tab" data-content-id="search"><var id="lang_tab_search"></var></span>
26
+        </div>
27
+        <div class="alignBar">
28
+            <label class="algnLabel"><var id="lang_input_align"></var></label>
29
+                    <span id="alignIcon">
30
+                        <span id="noneAlign" class="none-align focus" data-align="none"></span>
31
+                        <span id="leftAlign" class="left-align" data-align="left"></span>
32
+                        <span id="rightAlign" class="right-align" data-align="right"></span>
33
+                        <span id="centerAlign" class="center-align" data-align="center"></span>
34
+                    </span>
35
+            <input id="align" name="align" type="hidden" value="none"/>
36
+        </div>
37
+        <div id="tabbody" class="tabbody">
38
+
39
+            <!-- 远程图片 -->
40
+            <div id="remote" class="panel">
41
+                <div class="top">
42
+                    <div class="row">
43
+                        <label for="url"><var id="lang_input_url"></var></label>
44
+                        <span><input class="text" id="url" type="text"/></span>
45
+                    </div>
46
+                </div>
47
+                <div class="left">
48
+                    <div class="row">
49
+                        <label><var id="lang_input_size"></var></label>
50
+                        <span><var id="lang_input_width">&nbsp;&nbsp;</var><input class="text" type="text" id="width"/>px </span>
51
+                        <span><var id="lang_input_height">&nbsp;&nbsp;</var><input class="text" type="text" id="height"/>px </span>
52
+                        <span><input id="lock" type="checkbox" disabled="disabled"><span id="lockicon"></span></span>
53
+                    </div>
54
+                    <div class="row">
55
+                        <label><var id="lang_input_border"></var></label>
56
+                        <span><input class="text" type="text" id="border"/>px </span>
57
+                    </div>
58
+                    <div class="row">
59
+                        <label><var id="lang_input_vhspace"></var></label>
60
+                        <span><input class="text" type="text" id="vhSpace"/>px </span>
61
+                    </div>
62
+                    <div class="row">
63
+                        <label><var id="lang_input_title"></var></label>
64
+                        <span><input class="text" type="text" id="title"/></span>
65
+                    </div>
66
+                </div>
67
+                <div class="right"><div id="preview"></div></div>
68
+            </div>
69
+
70
+            <!-- 上传图片 -->
71
+            <div id="upload" class="panel focus">
72
+                <div id="queueList" class="queueList">
73
+                    <div class="statusBar element-invisible">
74
+                        <div class="progress">
75
+                            <span class="text">0%</span>
76
+                            <span class="percentage"></span>
77
+                        </div><div class="info"></div>
78
+                        <div class="btns">
79
+                            <div id="filePickerBtn"></div>
80
+                            <div class="uploadBtn"><var id="lang_start_upload"></var></div>
81
+                        </div>
82
+                    </div>
83
+                    <div id="dndArea" class="placeholder">
84
+                        <div class="filePickerContainer">
85
+                            <div id="filePickerReady"></div>
86
+                        </div>
87
+                    </div>
88
+                    <ul class="filelist element-invisible">
89
+                        <li id="filePickerBlock" class="filePickerBlock"></li>
90
+                    </ul>
91
+                </div>
92
+            </div>
93
+
94
+            <!-- 在线图片 -->
95
+            <div id="online" class="panel">
96
+                <div id="imageList"><var id="lang_imgLoading"></var></div>
97
+            </div>
98
+
99
+            <!-- 搜索图片 -->
100
+            <div id="search" class="panel">
101
+                <div class="searchBar">
102
+                    <input id="searchTxt" class="searchTxt text" type="text" />
103
+                    <select id="searchType" class="searchType">
104
+                        <option value="&s=4&z=0"></option>
105
+                        <option value="&s=1&z=19"></option>
106
+                        <option value="&s=2&z=0"></option>
107
+                        <option value="&s=3&z=0"></option>
108
+                    </select>
109
+                    <input id="searchReset" type="button"  />
110
+                    <input id="searchBtn" type="button"  />
111
+                </div>
112
+                <div id="searchList" class="searchList"><ul id="searchListUl"></ul></div>
113
+            </div>
114
+
115
+        </div>
116
+    </div>
117
+    <script type="text/javascript" src="image.js"></script>
118
+
119
+</body>
120
+</html>

文件差異過大導致無法顯示
+ 1148 - 0
public/UEditor/dialogs/image/image.js


二進制
public/UEditor/dialogs/image/images/alignicon.jpg


二進制
public/UEditor/dialogs/image/images/bg.png


二進制
public/UEditor/dialogs/image/images/icons.gif


二進制
public/UEditor/dialogs/image/images/icons.png


二進制
public/UEditor/dialogs/image/images/image.png


二進制
public/UEditor/dialogs/image/images/progress.png


二進制
public/UEditor/dialogs/image/images/success.gif


二進制
public/UEditor/dialogs/image/images/success.png


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

@@ -0,0 +1,98 @@
1
+<!DOCTYPE html>
2
+<html>
3
+<head>
4
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
5
+    <title></title>
6
+    <script type="text/javascript" src="../internal.js"></script>
7
+    <style type="text/css">
8
+        .warp {width: 320px;height: 153px;margin-left:5px;padding: 20px 0 0 15px;position: relative;}
9
+        #url {width: 290px; margin-bottom: 2px; margin-left: -6px; margin-left: -2px\9;*margin-left:0;_margin-left:0; }
10
+        .format span{display: inline-block; width: 58px;text-align: center; zoom:1;}
11
+        table td{padding:5px 0;}
12
+        #align{width: 65px;height: 23px;line-height: 22px;}
13
+    </style>
14
+</head>
15
+<body>
16
+<div class="warp">
17
+        <table width="300" cellpadding="0" cellspacing="0">
18
+            <tr>
19
+                <td colspan="2" class="format">
20
+                    <span><var id="lang_input_address"></var></span>
21
+                    <input style="width:200px" id="url" type="text" value=""/>
22
+                </td>
23
+            </tr>
24
+            <tr>
25
+                <td colspan="2" class="format"><span><var id="lang_input_width"></var></span><input style="width:200px" type="text" id="width"/> px</td>
26
+
27
+            </tr>
28
+            <tr>
29
+                <td colspan="2" class="format"><span><var id="lang_input_height"></var></span><input style="width:200px" type="text" id="height"/> px</td>
30
+            </tr>
31
+            <tr>
32
+                <td><span><var id="lang_input_isScroll"></var></span><input type="checkbox" id="scroll"/> </td>
33
+                <td><span><var id="lang_input_frameborder"></var></span><input type="checkbox" id="frameborder"/> </td>
34
+            </tr>
35
+
36
+            <tr>
37
+                <td colspan="2"><span><var id="lang_input_alignMode"></var></span>
38
+                    <select id="align">
39
+                        <option value=""></option>
40
+                        <option value="left"></option>
41
+                        <option value="right"></option>
42
+                    </select>
43
+                </td>
44
+            </tr>
45
+        </table>
46
+</div>
47
+<script type="text/javascript">
48
+    var iframe = editor._iframe;
49
+    if(iframe){
50
+        $G("url").value = iframe.getAttribute("src")||"";
51
+        $G("width").value = iframe.getAttribute("width")||iframe.style.width.replace("px","")||"";
52
+        $G("height").value = iframe.getAttribute("height") || iframe.style.height.replace("px","") ||"";
53
+        $G("scroll").checked = (iframe.getAttribute("scrolling") == "yes") ? true : false;
54
+        $G("frameborder").checked = (iframe.getAttribute("frameborder") == "1") ? true : false;
55
+        $G("align").value = iframe.align ? iframe.align : "";
56
+    }
57
+    function queding(){
58
+        var  url = $G("url").value.replace(/^\s*|\s*$/ig,""),
59
+                width = $G("width").value,
60
+                height = $G("height").value,
61
+                scroll = $G("scroll"),
62
+                frameborder = $G("frameborder"),
63
+                float = $G("align").value,
64
+                newIframe = editor.document.createElement("iframe"),
65
+                div;
66
+        if(!url){
67
+            alert(lang.enterAddress);
68
+            return false;
69
+        }
70
+        newIframe.setAttribute("src",/http:\/\/|https:\/\//ig.test(url) ? url : "http://"+url);
71
+        /^[1-9]+[.]?\d*$/g.test( width ) ? newIframe.setAttribute("width",width) : "";
72
+        /^[1-9]+[.]?\d*$/g.test( height ) ? newIframe.setAttribute("height",height) : "";
73
+        scroll.checked ?  newIframe.setAttribute("scrolling","yes") : newIframe.setAttribute("scrolling","no");
74
+        frameborder.checked ?  newIframe.setAttribute("frameborder","1",0) : newIframe.setAttribute("frameborder","0",0);
75
+        float ? newIframe.setAttribute("align",float) :  newIframe.setAttribute("align","");
76
+        if(iframe){
77
+            iframe.parentNode.insertBefore(newIframe,iframe);
78
+            domUtils.remove(iframe);
79
+        }else{
80
+            div = editor.document.createElement("div");
81
+            div.appendChild(newIframe);
82
+            editor.execCommand("inserthtml",div.innerHTML);
83
+        }
84
+        editor._iframe = null;
85
+        dialog.close();
86
+    }
87
+    dialog.onok = queding;
88
+    $G("url").onkeydown = function(evt){
89
+        evt = evt || event;
90
+        if(evt.keyCode == 13){
91
+            queding();
92
+        }
93
+    };
94
+    $focus($G( "url" ));
95
+
96
+</script>
97
+</body>
98
+</html>

+ 80 - 0
public/UEditor/dialogs/internal.js

@@ -0,0 +1,80 @@
1
+(function () {
2
+    /* eslint-disable */
3
+    if (window.frameElement.id) {
4
+        let parent = window.parent,
5
+
6
+            dialog = parent.$EDITORUI[window.frameElement.id.replace(/_iframe$/, '')],
7
+
8
+            editor = dialog.editor,
9
+
10
+            UE = parent.UE,
11
+
12
+            domUtils = UE.dom.domUtils,
13
+
14
+            utils = UE.utils,
15
+
16
+            browser = UE.browser,
17
+            /* eslint-disable */
18
+            ajax = UE.ajax,
19
+
20
+            $G = function (id) {
21
+                return document.getElementById(id)
22
+            },
23
+            $focus = function (node) {
24
+                setTimeout(function () {
25
+                    if (browser.ie) {
26
+                        var r = node.createTextRange();
27
+                        r.collapse(false);
28
+                        r.select();
29
+                    } else {
30
+                        node.focus()
31
+                    }
32
+                }, 0)
33
+            };
34
+        window.nowEditor = {editor: editor, dialog: dialog};
35
+        utils.loadFile(document, {
36
+            href: editor.options.themePath + editor.options.theme + '/dialogbase.css?cache=' + Math.random(),
37
+            tag: 'link',
38
+            type: 'text/css',
39
+            rel: 'stylesheet'
40
+        });
41
+        var lang = editor.getLang(dialog.className.split('-')[2]);
42
+        if (lang) {
43
+            domUtils.on(window, 'load', function () {
44
+                var langImgPath = editor.options.langPath + editor.options.lang + '/images/';
45
+                // 针对静态资源
46
+                for (var i in lang['static']) {
47
+                    var dom = $G(i);
48
+                    if (!dom) continue;
49
+                    let tagName = dom.tagName,
50
+                        content = lang['static'][i];
51
+                    if (content.src) {
52
+                        // clone
53
+                        content = utils.extend({}, content, false);
54
+                        content.src = langImgPath + content.src;
55
+                    }
56
+                    if (content.style) {
57
+                        content = utils.extend({}, content, false);
58
+                        content.style = content.style.replace(/url\s*\(/g, 'url(' + langImgPath)
59
+                    }
60
+                    switch (tagName.toLowerCase()) {
61
+                        case 'var':
62
+                            dom.parentNode.replaceChild(document.createTextNode(content), dom);
63
+                            break;
64
+                        case 'select':
65
+                            var ops = dom.options;
66
+                            for (var j = 0, oj; oj = ops[j];) {
67
+                                oj.innerHTML = content.options[j++];
68
+                            }
69
+                            for (var p in content) {
70
+                                p != 'options' && dom.setAttribute(p, content[p]);
71
+                            }
72
+                            break;
73
+                        default :
74
+                            domUtils.setAttributes(dom, content);
75
+                    }
76
+                }
77
+            });
78
+        }
79
+    }
80
+})();

+ 0 - 0
public/UEditor/dialogs/link/link.html


部分文件因文件數量過多而無法顯示